Submind YouTube summaries
Thumbnail for Building and Using MCP Servers in Visual Studio

Building and Using MCP Servers in Visual Studio

Watch on YouTube

Video summary

Leslie and Stefan from the .NET and ASP.NET Core teams introduce Model Context Protocol (MCP) as a standardized framework, often described as the "USB-C of AI," designed to provide large language models with context and access to external data across various clients like OpenAI or Anthropic. This protocol offers significant advantages such as reusability across different environments including Visual Studio Code and Copilot CLI, fine-grained control over tool activation to optimize token usage, and the ability to authenticate into private resources. The presenters advise developers to initially utilize skills for natural language processes before transitioning to MCP servers when specific needs arise, such as requiring external authentication or deterministic tooling. They highlight popular implementations like GitHub, Azure DevOps, Context7, Playwright, and Aspire, which empower Copilot to read repositories, access documentation, automate browser testing, and retrieve dashboard logs effectively. In a live demonstration, the speakers leverage multiple MCP servers to assist Copilot in resolving a weak password validation issue within an ASP.NET Core application. This process involves reading GitHub issues, consulting API documentation, automating form filling using Playwright, and drafting a pull request, showcasing the seamless integration of these tools. The discussion also covers strategies for improving token efficiency by enabling only necessary servers and disabling unused tools within them. Stefan further details the C# MCP SDK 2.0, which supports the latest protocol revisions, session migration over HTTP, and attribute-based tool definitions. He explains that while standard I/O is suitable for local development and debugging, streamable HTTP is essential for distributed scenarios like Docker or Azure Container Apps, alongside features such as prompts for reusable workflows, elicitation for user input, and tasks for long-running operations. The presentation then shifts to building MCP servers using HTTP transport via the Web Application Builder, contrasting this approach with standard I/O modes and highlighting technical considerations like configuring routes after `builder.Build()` and handling specific HTTP errors. A key advancement discussed is the transition from stateful sessions in legacy protocols to stateless multi-roundtrip requests in the new SDK, which resolves scaling issues by returning `InputRequired` results instead of awaiting continuations. This architecture also introduces improved elicitation patterns where missing parameters are requested via error responses rather than session-based metadata. To streamline development and debugging, an Aspire-based MCP server template is introduced, offering built-in observability dashboards and the MCP Inspector tool for visualizing raw JSON responses, while client ID metadata documents help simplify authentication without requiring dynamic client registration.
Read the full video transcript
So, um, nice to see y'all. I'm Leslie. I work on the .NET team and I also host the Visual Studio Toolbox show on YouTube and Twitch. >> And I'm Stefan. I work on ASP.NET Core and the C MCPS SDK filling in for Mike who retired early. So, that's my excuse. No. [laughter] Couldn't get him out of retirement to do this for me. >> Yep. and we're here to talk about everything that you need to get started with building and using MCP servers in Visual Studio. So, just to get a sense of the room, show of hands. Who knows what an MCP server is? >> Okay, >> it's the is are you awake question? [laughter] >> Who's used an MCP server? >> All right, cool. So, um yeah, this is basically going to be a bit of a crash co. So, if you've never used an MCP server before or don't really understand why you should use one in the first place, we're going to talk a little bit about that and we're also going to talk about how you can get started with writing your own. So, curious, has anyone written an MCP server? Okay, cool. Handful of you. Awesome. So, we're going to start from like ground zero and we're all going to get on the same page and hopefully by the end of this talk you'll feel rare up and raring to go to write your own. So, just a little agenda for what we got going on. We're going to start by talking about what MCP servers are just so we're all on the same page as well as why you should consider writing one. We're going to do some demos about how to use MCP servers in Digis Studio because BS in particular makes it pretty easy to get started with MCP servers in my opinion. And uh we're also going to talk of course about writing MCP servers specifically using the MCP car SDK as well as talk about some of its new additions in 2.0 which fresh out of the oven as of yesterday, right? >> Yep. Yesterday afternoon, like 24 hours old. >> Yeah. So, still super new. Go try it out. And uh finally, we'll wrap it up with some resources for you. Uh so you can catch up on anything that we talked about or maybe didn't talk about. And if we have time or even if we don't have time, we'll be around to help answering questions that you got. So, starting from the top, what is an MCP server? Do you want to kick it? >> Sure. Yeah. Um, MCP stands for model context protocol. So to, you know, a bit of triviality, it provides context to the model. Who knew? So it's all about context engineering these days, right? Or I mean, we're several was prompt engineering. We're now in Tuckwin reduction. MCP can help you with a lot of this. Um, so there's a lot of strategies to basically um add custom functionality to your agentic um, you know, programs, operating systems, whatever you want to call them. And um, MCP is a standardized way where you can um, write a server in a programming language of your choice like C and have it work not just with OpenAI, not just with Anthropic, but with a whole suite like basically the entire ecosystem, right? supports MCPs. Like most people don't even say servers anymore. >> Yeah, [laughter] people get it. And um yeah, because the before times before there was MCP, it was kind of a hassle to be able to connect to a lot of those external resources and data because you'd have to know the exact connection between the client you're going to and the resources you're trying to connect with. And that could be different for every single connection you're trying to make. So that's not really fun. It's like a bunch of wires to use the metaphor because of you've probably heard this metaphor before. It's like the USBC of AI. And I know it's super cliche at this point, but honestly, I think that's the best way in my opinion to describe it. At least that's how I remembered what an MCP server is. Because USBC, it's meant to be that universal charger that just works for everything. You only need to travel with ideally one cable and not a bunch of different types. With MCP server, same thing applies. So one port or one protocol to rule them all. It's the one ring. So as for why you should use an MCP server, there are a couple reasons. Of course, the biggest one is whenever you want to attach to external data with your LLM or co-pilot. This is when you might want to invoke an MCP server in the first place. Um especially when it's information that your LLM isn't necessarily going to be trained on, such as your personal sensitive information. Um, but it lets you use natural language descriptions in order to access in order to have the agents discover those capabilities. So, no additional wrappers or SDKs required to learn. It's reusable everywhere. So, regardless of where you write your MCP server, um, it's really compatible with most places at this point that support MCP server. So, if you're writing your MCP server in Digital Studio, but you want to use it in VS Code, should work over there. should work over in uh like the copilot CLI wherever you want to go. A lot of the times if you're trying to install an an existing NCP server, there's going to be like five different sections regarding the uh the client location that you want to install it to, each with their own pretty straightforward copy paste instructions. So, uh very reusable. And finally, you get a lot of fine grain control over the tools that make up that server. So you can choose to enable or disable a subset of them depending on what you're doing, which is especially good if you're trying to save tokens, which we'll talk more about later because tokens are a very precious commodity these days. >> And you don't just yolo all the command line tools like you actually enable them individually. >> I mean, you can, but um that it's going to cost you. >> Good. Yeah. In more ways than one. >> Yeah. >> All right. So, one of the big elephants in the room, especially with AI, anything nowadays, is when do you use one thing over the other? When do you choose to write one thing or the other? So, here's a nifty chart uh with some of the three main things that tend to overlap a lot, especially when it comes to writing or figuring out what to write, that being MCP, server, skills, and CLI apps. So, >> yeah, like this is a question that I've gotten asked a lot. I read that MCP was dead about 18 months ago and yet the usage keeps going up and I keep getting more bug reports. So, first of all, consumers are looking for MCPs, especially um if you're um trying to distribute internally or externally. Um the tooling, which we'll demonstrate soon, makes it very easy to integrate. Um and um it also offers some features um similar to Signal R. raise of hands who who knows what signal is that um yeah allow you to integrate with the harness in ways that uh skills and CLI apps uh cannot and I'll show you that uh via like maybe if you've heard of elicitation spoiler we we'll get there so there are things like that that's not to say that skills are are bad right like they're great um when uh you know it's well suited when you're trying to describe in natural language um a process that you want to follow but it's not as deterministic as an MCP um CLI is great when you want to script if you want to pipe output to another you know agent can write a script using CLI tools especially if it's something that it's already trained on but MCP really increases the discoverability um agents are well trained on finding using and discovering the tools available in MCP servers >> yeah and I'd say if you're trying to write something and you're not sure especially if you should start with a skill or an MCP server my advice has always been start with a skill And if you find that you're reaching a point where it's unable to do something that you need it to, such as like authenticate into a source where you can get that external data, then maybe it's time to transition into writing an MCP server. Scales are usually a lot easier to write. So just I think it's good to start there first and then expand later. as a real world example. Um, one my team were currently working on a Nougat MCP server and there was a lot of debate initially as to whether we should make it a skill or if we should make it an MCP server. We opted to go the MCP server route because ultimately we wanted to authenticate into people uh enterprises private marketplaces in order to be able to handle uh package updates or security issues, vulnerabilities, all that. So, one example, here's some popular MCP servers. If you're not sure where to start, um, here's some that I use on a regular basis. Um, we're going to talk about three of these in a demo that's coming up. But, uh, GitHub's a big one. If you're an ASDO fan or Azure DevOps fan, there is an MCP server for that as well. MSLearn, which lets you access, uh, MSLearn docs. Azure, which is huge. It has a ton of tools. Again, a great example of uh just checking the ones that you care about. But for Azure, I love it. Especially as somebody who has to write custoto queries a lot for telemetry purposes. It's not a fun time. That tool literally uh erases days of work that I'd normally spend trying to write this crazy query. So, love that. And if you don't know what custo is, good for you. [laughter] Um, Playright, it's a interactive browser-based automation experience that is really cool that we're going to show off as well as Context 7 which is able to access um API docs and Aspire even has an MCP app now or MCP server that I recently tried out. So that's really cool. If you've ever had to copy paste console log information from the Aspire dashboard of your Aspire app before to give it back to Copilot, you don't need to do that really with the MCP server because it just has access to that stuff now. So that's really cool. So just to name a couple, but um yeah, they're sprouting out sprout sprouting up. So if you feel like there might be an MCP server available for a given uh like software that you use or experience that you use, Google it cuz it might pop up. So now let's do a crash course on how to get started with using NCP servers in Visual Studio. And we're going to swap over to VS. Right. Uh hopefully everyone can see my screen. It's all right. Great. Cool. So um getting started with MCP servers. First thing is we want to actually install some. So fun fact, you can go to the extensions tab now and select MCP registries. And this gives you a window that's similar to the extension manager if you've used that in Visual Studio before except it gives you a bunch of different MCP servers you can install. It's not perfect. I have filed a couple issues such that I hope we have the ability to one day sort these by um popularity. But if you know what you're looking for, you can search for whatever such as like Azure ones and things like that. Uh, so this is the same registry as the GitHub MCP registry. So if you were to Google that right now, that's the exact same catalog, but not every MCP server that exists out there is in this registry. So, um, worst case, if you can't find it here, just Google it and it should pop up with its own GitHub repository with all the instructions that you need to either install it yourself or get copilot to install it for you. But once you find what you want, so like for example, Context 7, which I was going to demo in a few, you'd click install. And when you install it, that server is going to end up in a file called the MCP.json file. And you can see that if you click on the little wrench icon with all the tools in your chat. And I mentioned contact 7. So I can click on the three little dots next to this one and choose edit. And so that's what this file looks like. It's a JSON file that stores all of the information needed to have Copilot attached to the different MCP servers. >> Where is that file? Yeah. So, by default, this one is in your entire VS workspace. So, any MCP server that you're installing like from that registry window is going to end up available for every session of VS from there on out. But if you want to have um servers be exclusive to a given solution, you can um two ways, you can create the MCP.json JSON file manually and just put it at the root of your repository. Or you can do uh click on the tool icon again. You can hit plus and you can choose to add an MCP server this way where uh you also have the ability to choose between it being a global server or a solution-based one. So pick your poison. There might be cases where you want it just for your the rest of your life or you might just want it for a specific solution for whatever reason. So whichever you need and I think what's also cool about VS and it's something that VS Code doesn't really have is that it makes it really easy to configure your MCP servers especially if you don't want to engage with the JSON directly. So, uh, Context 7, for instance, if we clicked on those three dots, you can choose configure, and then you get this nice little window of information such as the general overview about what the server is. Some servers are going to need like an API key or additional environmental variables in order to connect properly like this one does. So, there's an inputs tab where you can put in your API key there instead of um having to manually add it in the uh JSON file. You can also view all of the tools that make up the MCP server here. And you can also choose how much you actually trust the MCP server. You know, authors like authorization and security is a big thing with MCP servers in general, especially because they are essentially accessing external information that's most likely going to be sensitive in a lot of ways. So, we wanted to make it so that um you're in the know about both when the MCP server is about to be accessed and how much you care about getting those notifications. So, you can choose to always trust the server if you're in full-on trust mode if you want. So, once you have all of your NCP servers that you want, then you can actually use them. So, let's see three of them in action. So to do that, I have got this.net web app. Um, it's pretty basic. It's one page. It's like Finish Fidget Spinner the game. Or if you've ever played uh one of those clicking games like Cookie Factory or something where you just spam a button over and over because you're bored at work and you want to see some fun ASMR pop up on screen. It's like that. So >> you'll see. >> Yeah. The fun thing about demos live is that demos are like I don't know. We're going to take our time. >> I hope we'll see. >> We're go really slow. >> You guys know those idler apps, >> right? >> Oh my goodness. >> It's so so much dedicated to idleness that it's choosing to be idle when it boots up. >> It looks like it's >> I think it might have. Well, or it's trying to Oh, yeah. Yeah. >> Did it do it? >> Oh, okay. Oh, there we go. Oh, do we have another monitor hidden somewhere? >> I don't think so. Oh, wait. No, it's >> halfway off the screen. >> I think it was because I was practicing on multiple monitors. >> Like alt space, left arrow. The who? [laughter] >> Alt space m left arrow. >> It's fun. Yeah. Let's see if we can >> Oh, there we go. >> Okay, here we go. >> Yay. Success. We only need one of these, though. All right. So, this is what I'm talking about. You literally just spam a button and you get fun little achievements for however much you click on it. So, I got one for 10 clicks and 3 seconds. So, I'm a speed demon now. So, >> pretty impressive. Yeah, >> you need a macro. >> Oh, yep. Macros are That's cheating. >> That is cheating. >> Yeah. >> And um now obviously it might take a while to get a 100% on all these achievements. So, there might be a point where we want to save our progress and come back to it later. So, I've added a little form down here where you can set up an account to save your progress. However, I have an issue where for the password, I'm expecting it to be a secure one. So, one that's at least eight characters, has a capital letter, has a number, that sort of thing. But I'm noticing that I can get away with using one of the worst passwords ever, and I'm rewarded for it for some reason. So, as an example, I'm going to use the password password. >> Yay. Oh, wow. Isn't that awesome? That's so cool. >> Do we allow that by default in identity? >> Oh, >> maybe not back compatible. >> The one password they tell you not to do in your very first computer class in grade school. So, obviously, we wanted to address that. And I already have an issue in my GitHub repo that's set up to address this one. So, uh involves weak passwords. My expectation was as I mentioned earlier eight characters one digit one uppercase letter at the very least and it has to do with a class that I have in my project called signup validator which is using an API called fluent validator. So it is over and I'm going to stop debugging. It's over here. Fluent validation. And so I'm probably going to need to add some code here in order to make that password a little bit more secure. So, there's a prompt that I've set up and I'm going to walk you through it because it's pretty long, but it's going to use a several different MCP servers to address this problem. The first thing it's going to do is uh take a look at that GitHub issue that I just shared revolving around the leak passwords. You'll notice that because I'm using the uh it's going to call the GitHub MCP server. I don't even have to link to it. It just has access to my repository. And even if I didn't have it open right now, I could just say go check out my achievement unlocked repository and look at that issue and go uh help me address that issue. And even if it was a private repo, this one's public, but if it was private, the um MCP server could also access that as well. So um that's one good example. And you'll notice, I can't highlight it unfortunately, but my mouse is next to the tool call that it just did, which was Oh, I just lost it. But it basically said issue read. And the second thing I'm having it do because I want the co-pilot response to be a bit more grounded. I want it to go take a look at that fluent validation API documentation to make sure that what it's adding is correct and up to date. And >> that's the context 7 server. Yeah, that's the context MCP server or context 7 MCP server. So, it made a call there and you can see one of the calls here. It's MCP context 7 resolve library ID. And so, it just added two more lines. And then finally, the uh last MCP server that I'm going to be using is Playright, which is a browser automation, and it's a fun way to be able to test out functionality. So in this case, I'm telling it to run my app again and then try that same form fill out behavior and see what happens. And hopefully the password is handled. So I didn't uh click on anything. I'm not touching the keyboard. I am now because I want you to see the the progress that it's going to do. But playright is now going to do its thing and uh act like it's the user in this case and fill out the form. So, I can see next to in the copilot chat that it's filling out the form and it chose to use a password that doesn't work. So, that's good. We're not automatically getting rewarded with a bad password. Not that capital P password one is any better, but it's a step in the right direction for sure. Uh, so it just entered that stronger password. >> Here's where I'll promote ASP.NET Core in 9. identity added pass key support. Pass keys uh prevent fishing password one. So you could uh maybe try that. >> Pass keys are the new password >> next iteration. >> We should file an issue on that. >> I will. >> So once it's done that um you can see it's making a lot of tool calls related to playright right now. And it's also really cool because the playright MCP server can take a screenshot of everything that happened and send it back to co-pilot who can then tell me what's up and what what the status is. And finally, once it's done all that, I've also asked it to draft me a PR based off of this off these changes and everything that it did. So, it's doing its thing. So, it says that the good old password was rejected. Capital Password one was accepted. We got some more work to do after that. And then it's going to draft the PR. But pretty cool, right? Very cool. And yeah, I mean it shows you kind of some of the more popular MCP servers like GitHub, Context 7, and Playright in particular. I normally run that >> headless so it doesn't interfere with me, but it's great for the demo. >> Yeah, I I use Blot because I'm I'm a very visual person, so I like and I don't always trust Copilot to be doing what it says it's going to be doing behind the scenes. So I like that it can call the playright MCP server to actually run the behavior I'm telling it that I want to check. Um cool. So in that case it looks like the PR was also created. I can link to that. Yes I do. So there it is. And I like having Copilot make my PRs because they're a lot more detailed than I could ever come up with sometimes and it's [clears throat] a lot faster. So there we go. That is three MCP servers in action. Pretty cool stuff. I love my MCP servers. So, now we got to talk about the other elephant in the room before we proceed into writing MCP servers, and that is how to use MCP servers efficiently. Also known as how to save your freaking tokens because my goodness, they are they're going away so fast. Um, so MCP servers, they can take up tokens, which is why I think the biggest things to remember, especially if you're just using MCP servers, is to enable the servers that you need. So if you're working in a NVS for a given session and you know you're going to be spending a lot of time in a repository, probably want to turn on your GitHub or your Azure DevOps one. Um, if you know you're not going to be using Azure in any way, shape, or form, maybe disable the Azure MCP server. The reason for that is because um Copilot anytime you give it a prompt, it's going to be looking through all of the enabled tools and NCP servers that you've got, which eats up a lot of tokens, even if 98% of them are uh irrelevant. So, you don't want it to do that. So, uh on top of that, when you do have the servers that you need, if you find that some servers have a ton of different tools, then you might want to consider turning off the ones that you don't plan on using. So, for example, GitHubs does have a lot. It has 47 tools. So, if this is a time where it's fun to explore and check out all the different tools you can use, and if there's ones that you don't foresee yourself using anytime soon, then it might just be good to disable them. The good news is is that with each new VS update, a lot of NCP servers are being added by default, but they are disabled by default. So, you're not going to be hit with a surprise token bill um if you choose to go that route right away. But it also means that you need to go through that to uh that tools window and make sure that the ones that you want and the ones that you don't want are enabled or disabled accordingly. Um other than that, I think just the big picture beyond that is again make your prompts as specific as possible. Ideally, it's better to get a specific list returned than a list of everything, which again can eat up a lot of tokens. So, those are just some good ground rules to use when you're uh using MCP servers, especially, but also goes with writing MCP servers. It's definitely something to think about. Like for instance, if you're writing an MCP server where you have one tool that returns all the data, it might also be good to have a tool that has that returns a subset of the data. So yeah. All right. So that is using let's talk about writing. >> All right. My section I saw the hand though. Um, we will have questions at the end, but if there's anything interest like so you're saying to like future earlier like select like these Please. >> Okay. So the question being can you have a scenario where MCP servers are accessed for just like a given workspace instead of >> like sub solution. >> Is there a way for your tips to save tokens not be such a manual process? >> Oh I see. Yeah. So can some of that uh selection be automated? Yeah. Good question. Um, currently not really. I that is a deep wish in my heart and I hope it happens soon. I know like stuff like auto the auto tool is coming into place on like the VS code side as it relates to models and stuff and I hope that can get extended to other tools like the MCP server because yeah, you're right. That is very annoying to have to go through and uh enable disable for any given situation. And I wish it would be I wish it could get kind of smart about knowing what's relevant and what isn't. So, good question. And also, I think that's worth sharing in the developer community. Um, just like as an as an ask yet, which that's going to be my if you guys give um good suggestions for things, a lot of my advice would be to write it in the developer community. I promise real people, including myself, look at it and tell your friends to upvote it. Like, I'll upote them. Like, email me after this and I will upote that idea especially. So, >> stop brigading if your friends are real and they want it. Um, [laughter] >> sweet. >> All right, so on to writing MCP servers. So now we're gonna talk about how to write MCP servers in Ruby. No, I'm just kidding. C. I am the lead developer of the MCP C SDK. Not the C MCP SDK. Oh, sorry. >> Oh, I just wanted to full screen it again. >> Oh, yeah. Make sure we're full screen. >> There you go. >> So, um, yeah. So, we're just going to give you some brief intro as to what it is. Um and uh as we mentioned just yesterday we released 20 of the SDK that corresponds with the 20260728 protocol revision which is the biggest protocol revision MCP has had to date. Not many servers or clients support it yet but our SDK does by default as do the other tier one SDKs um right now. C is one of three um or I think Go might so it might be four. So there's Python, TypeScript, C and maybe go probably go and uh that's based on a conformance suite that um you know the protocol maintainers work on. Some of you might have heard that Anthropic made the protocol originally convinced a bunch of other companies like Microsoft and Google to jump on board. So it has broad compatibility and then um donated the project to the Linux Foundation. So now it's the Agentic AI Foundation. um we have representation on like the core maintainer um board. I'm in the transport working group. Um so uh we're involved in like shaping this protocol to a lot of extent um partly because they want to make sure that SDKs have good support for these uh new features and the focus um recently um with both the SDKs and the protocol itself is to move from a kind of stateful sessionbased model which is um you know very um designed for like a single process lifetime. One of the common ways of uh using MCP servers are standard IO. Um and the other common way is HTTP. Um Leslie just demoed both of those for you. So when you want to use standard IO, right, that's council right line, council read line. This is where Visual Studio is launching the server for you as your user. So, Playright standard IO only way it's going to work unless you know Playright wants to spend money running browsers in the cloud or something and then it might have a tough time uh accessing local host without a dev tunnel. Just easier if you run things like that locally. Um on the flip side like context 7, if you're going to access an external resource anyway, um you don't want to have to download everything locally. Um you might as well just go straight to the source. That's an HTTP based u server. Um, for the most part they have similar capabilities. But one thing that was really dogging MCP server developers using HP transport particularly at Microsoft was um what happens if like in the middle of the session a server gets recycled um and you want to continue working now like do you know in the C SDK we had some features which would allow session migration but that required extra work. it requires like an external store. Um, and HTTP which uh this transport is based on um is generally known as a stateless protocol. Like one request uh doesn't affect the other even if they're on the same TCP connection. Windows off notwithstanding. We pretend that doesn't exist. Um you know obviously um you know there are some things where you might be using like client certificates where there might be some state share between your requests but generally not. And now MCP built on top of HTTP um has no protocol association between requests which means that if a request gets uh like roundroined uh to another server sorry went backwards. Um things will be dealt with pretty well. So we'll get more into that later. I have a fancy diagram but let's just start with like the most basic thing you can do with an MCP server. And this would be a tool. um a tool you can think of a lot like controller action, a minimal endpoint. It's a request response um like a post request for the most part. Um unless you um mark your tool via metadata as like readon and item potent um you should expect that tool calls might do something um destructive. >> And a lot of the time it really can be as simple as just a method that you'd write in any other program. Like in this example, it's just a basic echo method. But the C SDK for MCP is very attributeheavy. So you can literally just add an MCP server um MCP server tool attribute to the top and it's a tool. Voila. So >> yes, and um we're going to get to a Visual Studio naturally and show you this in a project and we'll show you how you can wire these all up. But the attributes are definitely the primary way for specifying this kind of metadata. But um C offers very low-level APIs as well. So you can call um MCP tool.create with uh whichever metadata you want. So it's very good for writing dynamic tools and stuff as well. Though client support tends to be a little so so if you know tools start changing underneath you and so forth. Um some people have tried it but unless you're writing your own client which you can also write with the C# SDK not part of this. Um maybe don't rely on that. So tools um so here you see um a description is a pretty important part of each tool and normally um we infer the name uh a lot like you would in a controller action or whatever from the name of the method for your tools. Um, but you can specify that via >> Yeah. Um, and and I know descriptions, they're technically optional, but we're going to tell you they're mandatory. Like if you if you want co-pilot or whatever um LLM client to do what you'd want it to do, which is invoke that tool like the way that you want most of the time and you want it to be more consistent, it's really important that you come up with a good description. You can even have co-pilot write it for you, which probably makes it even stronger because now it knows what you're talking about. But if you leave out the description, you're kind of playing with chance a little bit, unless your um title of the tool is really freaking good and you're looking out that day. So, >> all right. Um and then also um aside from tools, it's not the only thing in MCP. Um you can also support prompts and resources. So resources are like what's used by context 7. um instead of taking arbitrary parameters that can be JSON serialized and objects and whatnot um where you're parsing a URI string um and then you're just returning the resource often from a file system you might have a mime type so you could return you know an image JSON Excel document whatever um and then prompts are um parameterized um kind of uh workflows that you often give to the LLM and they're in the clients that support it um often invoked via slash command um and then you can select your prompt and then um much like tools it takes parameters but instead of um giving you just like a a result it tells uh the agent like how to do you know a common workflow you can kind of think of it a little bit like mail merge in a lot of cases um and then elicitations um I'm curious has anyone used elicitations does anyone know what they are. All right. So, this this is where we're starting to get into advanced MCP. Um, this is now the only fully supported server to client request. So, we're doing something that HTTP normally can't do. Um, so normally when you're trying to take input from an agent, you just specify a parameter. You can supply descriptions for those parameters via attributes and then the agent will give you the parameters you need. But sometimes um for things that are important um you don't want the agent to guess what the user might want. Um you might want to give the user a specific set of options or prompt them with a text box. Um so you know that they entered that detail. Um and that's what elicitation is for. Um in the past um since this was built um on standard IO uh or stateful uh HTTP requests which had a session um the responses to an elicitation request um would basically just come as a JSON RPC response um as uh from the client to the server over the standard I IO transport um or just you know we would send a response in an issue request, which was like really unwieldy. Um, and it would have to um come to the same server, and we'll get into that in a second, but I made this uh macro a while back. Um, kind of shows you um how I think uh most people look at MCP >> like it's a lot. When in doubt, you're 98 99% of the time it'd be writing tools. I think prompts are nice from an enduser standpoint because you probably best know the best ways that your MCP server and its tools are going to get invoked. So if you figured out the magical unicorn prompt that works for you every time, why not share it as a prompt for your end users to use too? But >> y and I didn't go into sampling or roots. If we have time, I am more than happy to just know that it is obsoleted as of yesterday. You're on a 12-month clock. Um and not many things is supported to begin with. So it >> it's really run away there. >> Proves the point I was trying to make. Um and then yes, HP versus standard IO. Um I kind of um ran this a little. But yes, um the big benefit of standard IO is it's simple to set up. You don't need to have a process that you manage running all the time. Um but and it allows access to local resources. Um but it can be harder to distribute. Um and it's a more difficult threat model especially if you like don't fully trust the MCP server. Um also off um if we have time for that we'll show the ooth flow. Um but um either way um you know streamable HTTP basically means that you know compared to a CLI where you might have to manage tokens and stuff yourself. You can just rely on Visual Studio to manage the access tokens and stuff for you. Um, >> I I'd say with uh standard IO versus HTTP, I think back in MCP's early days, it was pretty easy to just say start with standard IO, but honestly nowadays, like between some templates, one of which we'll show you in a sec, and just MCP m starting to mature a bit, it's a lot easier now to get started straight up with streamable HTTP as your option of choice. Um, so don't feel intimidated by HTTP, um, like I was back in the day because I think it's gotten a lot more accessible since. And I think as you alluded to, Stephen, like, um, it's really great for scaling to a lot of clients. When you start to think about publishing your MCP servers in particular, standard IO is great if you want to publish to like Nougat. Nougat has its own MCP server section and that's also the main pipeline if you want to attach to the GitHub MCP registry in particular. Um, but if you want it to be in a Docker container or in an Azure container app or something like that and um scale it that way, then streamable HTTP is your go-to. >> All right. Um, and then talking about some more MCP features, um, there are also extensions. Um, two of the primary extensions are known as tasks, which are for super long running tool calls. Basically, we won't focus on that too much for the VS perspective, but maybe for more of your longunning agents that could be cool. And then MCP apps, which allow your tools to basically return HTML. Um, and it can be interactive. You can have JavaScript. Um, and this can um, help you visualize the output instead of just having the agent summarize it text or hope that it produces a good visualization for you. Um, you can produce the visualization that will be shown directly to the user. Um, this is something that's supported in VS Code. We um, but we think it will um, be added to VS uh, if you give us enough feedback maybe if you like it. All right. Um, but in the meantime, let's just do some demos. Writing some C# MCP servers. >> Nice transition. >> Super good. All right. All right. So, I have this VS Live MCP demos thing ready for us. But the first thing that I want to show you is just how simple uh the project uh new template is for MCP. So Visual Studio, if you have uh the .NET workload installed um provides an MCP template out of the box. You can see that I've tried this a few times. We're going to create MCP server 3. Sounds good to me. um and um gives you a nice little readme that shows you how you can edit that MCP file. So, I'm going to start building and trying to find where this executable ends up. But in the meantime, here is uh the entire um program CS and um this is using the model context protocol package on uh Nougat and uh I updated it at some point. Oh, this is the template. The the rest of the project is uh updated to use the 20 release. Um fortunately, um all this code works. uh most for the most part we retained backwards compatibility um even if we do upgrade to 20 um but not if you use some esoteric features I'll say like tasks um which I mentioned is for those long running tool calls previously so this is a uh using the hosted package so you can see that it's um depending on you know extensions hosting which is where host create application builder is this gives do a web application like builder so DI and logging uh in particular but uh it doesn't have you like host ASPET core web server um with Kestrel and um but if you don't like DI or logging which I mean how how could you um then you can also use the core package and you know there's an alternative flow where you can go um MCP server factory um create async um or this is using an old package but it's MPC MCP server.create async. So um with this server I'm going to copy that path right here and I'm going to use the uh add custom MCP server. So that was the other option, right, when Leslie was showing you how to add a thing from the registry. So here I'm just going to call this random. I haven't even shown you the tool yet, but you can guess what it looks like. It's in random number tools. Um, and uh, for the command line, I'm just going to pass in this path and it's MCP server 3.exe. So Visual Studio is going to launch this. So >> global, >> one thing to note, what about that being global? >> Or you're keeping the MCP server global? Yeah, for now. Um, so like you can launch this MCP server under a debugger. Um, it's not going to be that helpful. So like all this output, right, you can say all right, the server is reading messages. Um, it's expecting me to basically send like the tool listing calls and the tool request via the command line here. Um, and you can see there's some logs about the, you know, server stream transport reading messages. Um, but if I actually want to load it in Visual Studio and debug this tool, which is very uh exactly what we showed you before, right, where you have the MCP server attribute. Um, here we're just allowing you to optionally support uh minimax parameters. Um, defaults work. Um, and then we're using our shared random number generator. So, if we load it, which it did fail to load um probably because I put in the wrong path, which is a common thing um when I start with the >> I do like that it has the um error icon though >> like on the actual tool to tool icon so you know. >> Yeah. Um, so if we go to edit instead of configure, um, you can see that I just copied twice, which was my mistake. All right, there we go. AI actually figured that one out hopefully. Um, all right. And then we can just re hit that and it's like, all right, perfect. Now it's running but it's not under debugger. So what do you do? Um well one is you can use the HTB transport which we'll get to later. But second um you can attach to process. Um these days we actually you know can have that executable there that you can search for. Um so we don't have a million. Um but you do have to run it. So is it enabled? >> It looked like it was. Yeah. All right. Oh, I need to zoom way in on this. All right. Give me a random number from 100 to 200 to show that I didn't use the defaults, for instance, but it would. Uh, and at this point, Visual Studio will say it's calling this and it needed to get the the listing. Um, now I'll zoom out again. should have maybe set that to uh trust so I won't have to click that every >> I don't know I mean random numbers are pretty untrustworthy >> dangerous yeah I mean was that actually um you know resistant to quantum computing it's like the same thing >> 103 is a pretty thorough number I don't know >> all right so and then of course you can now see that it's running and if we were to add break points and stuff you can see what the parameters are and so forth. So go again. So that's one way to do it. Um and breakpoint. Cool. And if you've ever used attached to process, that was not a big surprise to you. And then of course I will go back to the demos that I had before. >> All right. And um yeah, so like it is a little tedious to set up debugging with standard IO. I mean, attached to process has gotten a lot better over the years and VS um if you've been around with VS for a while, you probably seen that window evolve positively in my opinion. So uh yeah, because it used to be like half the processes were all just called net exe and >> yeah. >> Yeah, good luck. Yeah, I found that reattached a process typically attached to the most recently launched one that that was kind of a crapshoot. >> Um, all right. >> So, we could talk about the HTTP Yes. >> route a little bit. >> Yes. So, this is what we're showing with this Fireworks demo um which combines the HTV transport but optionally still supports snare standard IO. So, it's possible to support both in the same app. This is just reading uh the command line parameter. Um when you're using web application create builder by default, I don't know if you know this, but um one of the configuration sources is the command line parameters. Um so MCP transport which I have defined in a per solution here. Um I have both standard IO and HTB. And in standard IO, you know, you pass the arguments and you put in that mode. But for this purpose, um, to make debugging easier, I'm just gonna launch the Fireworks server under debugger. Um, gonna make sure that once it's going, we have a uh Oh, yeah. Okay. We'll see what that is. >> My popcorn ready. >> Yeah. All right. What's What's a demo without some side byside browser windows and single art? Okay. So, this is running in the default HTTP mode since we didn't pass an argument in for that. And it's listening on this 5399 URL. Um, this primary URL is of course serving regular HTML. But if you're going to the MCP endpoint, you can see that's not a normal 404. That's a a 405. Um, which means uh does anyone know what a 405 means actually? Okay, I I'll answer for you. It's method not allowed. Um, so MCP expects post request and the browser is sending a get request. So that's what's going on there. Um, so we're added some signal R. Uh, and you know, we're adding singleton static state, you know, like you do in demos. Um, and then, um, you know, this server shows you, um, kind of more of the features. We'll make this public in a second but um unless you do like add tools from assembly um this with tools is important. So even though you are um using the attribute um for fireworks tools here MCP server tool type um unlike say MVC controllers we don't automatically scan the assembly for everything with the attribute and this is primarily due to native AOT. um we're trying to make sure that if you're not using some of the tools, we properly trim them and this uh reduces your executable size and so forth. Um but if you do want to scan everything from your assembly, you can call with tools from assembly and we'll do that. Um that's not a trim safe API. >> So it's pretty similar to like when you're registering components like in a web app, right? >> Very similar. Yeah. Yeah. So this is just you know building on top of builder.services. Um this time we're using a web application builder instead of a host application builder. Um, but we're running the MCP server in some app. So, if you're running in standard IO, you call with standard IO server transport like we did in the project template you just saw. I might have brushed over that a little bit. Um, but in this mode, we're running with the HTTP transport. And then the last thing you have to do um is it's not enough in HTTP mode to say that's the transport you're using. You also need to configure the route. And typically in an ASP.NET Core app, you configure the route after you call builder.build. build and that's what's happening right here. So you can call mapmc um if you want to you can add route parameters there and stuff and read that in your MCP server tools with the HTB context accessor. Um but yeah so let me make sure >> also you just used a bunch of HTML to get like this result right? >> Yes. So, I mean this of course um or maybe I shouldn't say of course, but um when we're viewing the website directly, this is using our normal um static files middleware um that you know returns this index.html. Um it's using signal r so it knows when the um fireworks start and it's uh actually written using raw websockets. AI is pretty good at reverse engineering the signal protocol. So I could just inline everything into um one HTML file. But this also makes it easier, right? Because this is an MCP um app as it's called. It used to be called MCP UI. Um which this tool um returns the HTML as a resource. So let's go back to full screen really quick. So you have this UI colon resource that's um you know returned over whichever MCP transport you use. This as noted can work in standard IO. So even though this is returning HTML um it can return HTML as a resource over standard IO. And um on the chats that support it like VS Code it will show in line. Um and here you can see that we're setting a special man. Do I need to use like magnifier there with for the tool tip? >> Oh gosh. >> Um let's see. I'm really bad at using magnifier. >> Wait, I think I know it though. >> Oh, there. >> All right. See, so you can almost see it. Text HTML profile MCP app, right? So, this is specifically for MCP. And then our implementation of this is just a resource instead of a tool. Let me X out of that. Hopefully that will just zoom out once I do. Um, this is instead of an MCP server tool, it's an MCP server resource that responds to requests for the fireworks stage and then returns all the HTML text. Um so and then the tool which launches the fireworks is uh using a API that is in an extension package um which is the um model context protocol extensions.app. So if you look at the dependencies whereas before we had uh model context protocol period which depended on like ancient versions of core and stuff you remember the sounds was like zero points only uh that here um we have uh you know model context protocol.aspnet ASP.NET Core. Um so if you're doing the HTB check based transport um you are using ASP.NET core uh for the server. Um in very very early versions of the SDK we had an HTV listener based API and Steven Toe made us remove it. He's like Kestrel um has the the hardening which is true. It's certainly um if you're running an edge server you want to be running Kestrel and not HTB listener. Um though HTB listener can be useful for some local scenarios. Um and it would be possible to write your own transport using the transport pluggability using that. Um but it's not built into the SDK. All right. Firework show. All right. Might be able to get some text. Let's make sure we have this loaded because I probably do not. I'm going to do the HTTP one since we're running that under debugger. Um, zoom in again. And the agent might be smart enough. It might know why it's launching fireworks because I am in a VS Live demo project. >> So spectacular. So here it's showing me since I still have it prompting me for every single tool invocation. Maybe that's a little unnecessary exactly what the parameters are going to be to my tool that's returning this HTML site. Um, one thing to note about the tools, right, is I'm injecting a single iHub context. That's like one of the benefits of using like the host and model is you get the I so you can include any services in the parameters. Um and if I service provider is service says that it exists that's where we'll get it from. Um otherwise um we'll deserialize the parameters that are passed to it. Um so in this case we have the title, the theme, the intensity and the finale message um all seen here. All right, we're gonna build something brilliant. Go and then boom. Y. Okay, so [snorts] and that's using SignalR to um so everyone sees the same thing. Um if this had MCP app support, you might see two of those. Um all right. And then one other really cool feature in this BS live demo thing is elicitation. So you guys want to see what elicitation is? Let's go. Um, so this one is another standard IO only server. No web application builder. I'm not going to bother trying to debug it. Um, but in the past kind of the way you would think about elicitation is I'm just going to show you the legacy first. Um, so inside your server tools, you can add all the metadata. This is the readonly item put in open world. These are all standardized as part of the MCP specification. So this will help the host know like maybe what to prompt users for. Like if they allowed readonly um stuff only then you know it wouldn't have to ask before um doing this release planning. It's going to help us plan a blue green deployment of source. All right. Um so in this case um this takes two parameters directly from the the host or the agent or the client which is the application we're about to release and the version of that application. But for some important questions like our um target environment roll out strategy um how much we want to initially roll out the percentage and um at what error rate would we want to roll back um that I want to ask the user. I don't want the agent to just guess at that. So um we're going to make sure we have this server loaded. This is already in the repositories like local nougat uh or sorry not nougat.mcp.json. So I'm just going to load the stateless release planner. So in this particular scenario since we're using the 20 SDK which is stateless the thing that breaks is this await. So, we're in the middle of the tool and with the um latest 2026728 protocol that was released yesterday, um as an SDK maintainer, I can't make this code work anymore because for this code to work, I need to have the elicitation response come back to the same server that made the request to to run the continuation. Um, and with the new version of the protocol, there's no longer an MCP session ID to basically track um, you know, which requests and response go together. So, elicitation will show you quickly what it is. Um, is yeah, help me release. All right. And since I don't have that many tools loaded, I think we'll figure that out. Who uses source.net? You guys all net developers. There's been some recent. [laughter] >> Yeah, Tanner has done some great work. Um, you know, including more of our libraries, Aspire and stuff all in that. All right, so it found my tool. It's applied only those two parameters that are actual parameters to the tool method. And I'll allow that again. And then the next step is kind of the interesting part, right? So, this is where it's asking me, not the agent. Um, how do I want to do this? So, I mean, I always go straight to broad. I don't know about you. I hear blue green is pretty good. Um, fortunately, I don't I don't deploy services. I work on libraries. Um, >> and then initial roll out percentage like 1% that seems like pretty tame. Um, but I have no bugs. So if there's like more than 1% of errors. >> Uh >> do you did you have copilot submit the PR2? >> Yeah. >> Yeah. [snorts] >> All right. So um in the legacy version of the protocol this is what that did and this response. So this is response would be sent um with a new HTTP request if it was using HTTP. Um and uh boom and it planned released and that actually did update source.net. No, I'm just kidding. Uh, it just responded with some text that said it would, but that was mostly to show you, um, you know, you, you saw as I shared the, you know, uh, multiple choice questions that it gave from your, uh, single select, you know, enim schema. There's also the number schema that takes the the numbers. So, basically allows you to, um, provide a specific form with specific, uh, inputs to the user. Um, >> we just decided to use an SAT word for some reason. Elicitation. >> Yeah, >> this is like followup or >> I don't think I knew what I barely knew what elicitation meant. Yeah, I don't know. It does sound like an SAT word. All right, so I said this was the legacy way of doing that and that this doesn't work anymore. So, okay, what's the new way of doing it? So, the new way of doing it is called multi- roundtrip requests, and that's the code we're really running um with the 20 SDK, and it still worked with Visual Studio. Um, and basically the key insight here is that if you're in a stateless server and you don't know if the server that asked the question is actually going to get the response, maybe if you ask the question, you should just return an error and say, "Come back to me with the the full request plus this extra information I need." If it's another server that ends up getting the new request, it has the original request copied to it, so it effectively knows what to do. And um so in this particular case um instead of awaiting an elicitation async um you send a oh there's me trying to put in vin things. Um okay so you basically return an input require result. So in this case you have the same schemas right that we saw earlier and I'm too zoomed in but instead of awaiting that as part of an elicit async request we return it basically as an error. So you see that we have this result or alternate and uh until we have basically all the input that we need um we return an error result which is like send us this request again with these inputs uh and then no matter where that goes um we um can handle that. And then there's also the ability within these multi-roundrip requests to provide a string um that basically carries state between those requests. Um I will say that in this particular case we're just doing like B 64 uh encoding and decoding like from B 64 string. Um, this is fine if you understand that a user can like modify the state naturally. Um, if you don't want to allow that, I recommend using data protection if you know what that is. That's what underlies like authentication cookies and stuff so you can encrypt the payload. Um, and it's pretty easy to use in ASP.NET Core. Um, all right. So, we that that's the the end of the the demos I needed to give. So, I can go back to the slides. Oh, I well I have one more demo actually. >> Oh, of course. >> Aspire. >> I needed to get and and the inspector, which is very cool. >> Yeah. So, I don't know how many Aspire talks happened uh at VS Live yet, but uh here's another blurb about Aspire because Aspire is cool. And um Maddie will be mad at me if I don't talk about Aspire for five minutes. But uh I'm talking about Aspire because we talked a little bit about um the kind of tedium that comes up with setting up debugging especially for a standard IO based MCP server. Um and I feel like HTTP is certainly better to hook up, but it still requires some steps. And I got frustrated one day and thought maybe it would be good to like aspire my MCP server uh one for that reason to make it easier to debug too because I get access to all of that good um orch orchestrating stuff. So in the event I want to expand on it later like adding a database or a cache or something that's easy to hook up. and three, because it comes with the lovely observability dashboard that I can use to view pretty much every metric and console log happening while I'm in development mode. So, I then turned that Aspire MCP server into a template, which I will link, which I've linked at the end of this talk. But here's what this looks like in action in case you're curious. And I did not even Oh, well, I have it right there. So, it's just called the Spire MCP server app. And I'm gonna keep the name as is. >> Is this built into Visual Studio? >> This is not built into Visual Studio. So go to the I have a link to my GitHub repo for this. Uh, and it's pretty straightforward to install. It's just and then it's just like a net new command after that. But once you have it, it looks a lot like the existing MCP server templates that we have except there's an appost. And again, you can do this manually. So I before I did a template I just added an at post um class and that contains a couple main components that we're talk about. One of course is the MCP server itself and we're also attaching um telemetry using open telemetry to it which is why we have the HTTP health check and also something called the MCP inspector is the other thing. The MCP inspector has its own Aspire integration. However, you can use this completely separate from Aspire. Um, it's an npx call. It's like npx at model context protocolinsspector. But if you don't want to do that, understandable. It's like outside of your net mode. Um, that's the other reason why I wanted to make this template. Um, and I'll show you what that does in just a second. So, um, first things first, if you're unfamiliar with Aspire, it is a really nice way. It's a polyglot framework that lets you easily orchestrate all the different components that make up your application without needing to know how to attach each one individually. And with it comes its own observability dashboard where you can view um console logs, a structured version of those logs, traces, metrics, etc. Um in addition to that in this template, it comes with two main resources that we put together. The first being the MCP server which is currently running in 7200 and that inspector that I was talking about. So if I click on that, this is I think a great way to debug your MCP servers um not just with breakpoints but also visually like if you just want to quickly see what raw text is being returned by your MCP server across your tools, your prompts, your resources, whatever else is making up your server, this is a great dashboard to use. So you're saying you don't just wait for the agent to make the right tool call like we were doing in the demo. >> Yeah, that's sometimes it can take a while, right? And sometimes you want to skip that middleman. You don't care about the formatting just yet. You just want to see the raw footage and this lets you do that. Now, if you were to use this inspector by itself, like outside of Aspire or outside of this template, you'd have to manually set up this connection by yourself. It can be kind of annoying, especially if you don't know the uh the URL in this example right away. But with the template, it automatically sets that up for you. So you don't have to configure anything. You can just hit connect and then you get access to your tools. So because I didn't do anything to this template, by default, it comes with the random number method that we showed earlier and you can run it and just get some good old raw JSON. You can check out the history of the tool call. Let me expand this up a little bit. Can zoom in. Yeah. And you can see exactly what's being returned without needing to worry about formatting and things just yet because maybe you don't care about that. >> So the real reason to subh prefer the HPV transport you get to use it with this Aspire template. >> Exactly. Not to I guess >> the Aspire to launch it Visual Studio launches a >> Yeah. And again what's great about this is like it's set up through Aspire. So you got the app post that it's connecting to. Hate your break points. go go for it as you're playing around with um this NCP inspector. And um there's also different categories. So we're using tools right now, but if you have a um like elicitations as we demoed earlier, prompts, resources, you can check all of those out here in addition to all of the built-in Aspire tools and Aspire functionality. So really cool. Um yeah, and I've linked the template at the end of this talk, which speaking of which, we are reaching the end of this talk. Thankfully, [laughter] >> it was been a long day. So, um Oh, did you want to >> Yeah, you know, if I had thought about the order more, I would have shown this slide when talking about why we went stateless. Um so, this is the problem that um a lot of hyperscalers run into. Amazon, Google, Microsoft, everyone was clamoring to make MCP stateless because um being forced to basically make all your clients reconnect just because uh you know you scaled your servers or you took one down is a bad experience. Um so by making the uh HP transport stateless, right, by doing the multi-round trip request thing that I showed you, which is a little harder, it's a little easier just to be able to away instead of like, you know, B 64 encoding your state. The upside is that it's way more reliable. Um, it's way easier to scale. No matter whether or not the request goes to instance B or C, you're never going to get a session not found error, which was a big problem. Um, with any older MCP server that wanted to do elicitation in particular, um, I think that is or or a lot of us think um, who've been working on MCP that's a reason elicitation hasn't been as popular um, as it might be. So now that um this can work reliably um without session affinity which is always kind of a best effort is is a huge win um so yeah um kind of the spark notes version on this one. >> Yeah. >> Yeah. So I mean 2.0 is out in the wild as of yesterday. We talked a lot about the stateless core which is probably the biggest addition right >> and um yeah we also talked about multi roundtrip request um off >> yeah so in off the big new feature um is uh client ID metadata documents so one of the things that make off hard with MCP is that you have native clients um connecting not to just the server they're designed to connect with but any server um and if any of you have ever set up OOTH with a native client, you know that there's typically a a client ID and a client secret and then you have to configure the application in Entra to um register it and this ends up uh being hard when you're trying to support any uh client that supports MCP. Um so with client ID metad uh metadata documents um doesn't require your authorization server to support what was previously required which is dynamic client registration which was this whole flow to basically get a unique client ID um and client secret. Then you could do what's known as like the authorization code flow with PKC. Um now um we can uh easily support um basically any client um with any server as long as you um follow the provided um client ID metadata document and um how much time do we have? >> We've got like two minutes. That's why I was like Spark knows version. >> Yeah. So there's a Sparks version. >> I love going deep. Um so anyway um this is supported by the C# SDK and Visual Studio. So and VS Code. This is not something that like you need to go to VS Feedback for. Um it will pop open a browser um ask you to log in and then Visual Studio will manage the access token for you. Um one thing to note is um anyone can naturally impersonate any client. They can't impersonate any user. So, and this is kind of true with native clients in general, like um there's, you know, we can't ship Visual Studio with like a secret. Um, and with the client ID metadata document, there's no secret that says like I for sure Visual Studio, but you do know whoever's connecting to you is like really that person. They just might be using their own hacked client or whatever. But, um, that tends to be good for most scenarios. Um, cool. Um, >> all right. Yeah. So, that concludes our talk. We talked about a lot of stuff and some that we briefly touched on but didn't go into full detail. So, uh we've compiled a bunch of links uh for you to check out. If you scan the QR code, um it takes you to a website called URList.com and it's got all of those links just um concentrated in one spot so you don't have to hop around to remember where all these are at. Um, otherwise you can just type in the URL.combs-mcps servers to get access to all this. So this includes the stuff that we demoed um or demo apps that we use, documentation, the official anthropic documentation, the C# SDK for MCP and more. So uh please do check out those resources. And um last but not least, um I hope you enjoyed this talk. We um and if you enjoyed it or if you didn't enjoy it, [laughter] please complete the survey. Thank you. >> Thank you.