Back to Index

Building Protected MCP Servers — Den Delimarsky and Julia Kasper, MCP Steering Committee & Microsoft


Transcript

Welcome, folks, to the building protected MCP servers session. I'm Dan Delamarski. I'm a product engineer at Microsoft and member of the MCP steering committee. And I'm Julia. I work in Azure API Management at Microsoft. And the both of us are part of an MCP squad at Microsoft. So I guess that's why we are here.

Yeah. So we're again talking about protected MCP servers. And why is this even important? Why is this even a topic? Well, the thing is, when we talk about MCP servers and MCP servers that folks connect to their whatever clients, whether it's cloud desktop, VS Code, VS, not every server should be open because there's a bunch of different APIs that might require authorization.

They're protected. So naturally, your MCP server needs to be able to do the same. It is super important for remote MCP servers because anybody can access them. And especially if the servers are open to the broad internet and not behind a VPN. But it's not really relevant for local servers.

And mainly because locally, you can do a bunch of stuff already because it's just a binary. And we'll get to that in a second. Now, if you're building MCP servers and remote MCP servers specifically, one of the things that you're connecting to are likely third-party APIs, whether it's your own or somebody else's.

And that API requires user context. That API needs to know who's invoking it because different customers have different permissions. You might have different admin policies. So while your API does control through the help of an identity provider as to who actually has access, this needs to be somehow exposed to the MCP layer.

And, of course, your API will act differently depending on the credentials that you give it. If I'm an admin, I get access to a certain set of tools. If I'm somebody that's just a contributor, I get access to a bunch of different tools. Now, all these things considered, one of the questions I get asked a lot is like, "Well, okay, this is all great for remote, but why not local?

What's the story for authorization for local servers?" And the answer is kind of simple. Local servers are binaries on the box. They're binaries that run within the context of whatever machine you have. That means that that they can do auth in any way you can possibly have. Like, it doesn't need to be auth.

You can have credentials that are secrets. You can have certificates. You can have pass keys that are bound to whatever credential you have on the box. Like, it's just like you don't have any constraints whatsoever. That means that any APIs you connect to can also be done in any way with any of the off-the-shelf libraries.

There is, of course, special cases here if you do things like remote desktop and all sorts of kind of multi-user scenarios on VMs. But that's kind of out of scope for MCP. That's something that we left to implementers. Now, remote servers. Let's get back to that. So, one of the things that if you've browsed kind of the MCP specs, you might know that we have two different specifications.

There's one that is stable, that is March 26th, and there's one that is draft, that we worked very closely with a bunch of security experts to refine. So, for the previous specification, the one that is currently marked as stable, MCP required people that are building MCP servers to essentially spin up their own authorization server.

That means you are building your own token factory. So, if you want to issue tokens to an MCP client to authorize users, you're the one that has to craft those tokens and manage them and refresh them and assign them. Very complicated. It required people to actually be OAuth experts.

Like, if you want to build an MCP server that does OAuth, you need to understand how OAuth works end-to-end, including to the point of minting those tokens, which is very complicated. So, the draft spec that we worked with Anthropic and a bunch of security experts to refine actually does this clean separation between the server, the MCP server, which we call the resource server, and the authorization server.

So, things like token minting and managing token lifetime actually is not done by the MCP server anymore. It's done by whatever authorization server you're using. So, if you're using Okta, Auth0, EntryID, it doesn't really matter. You can just plug it into your MCP server and it's going to work with the clients that those servers can connect to.

And the spec, by the way, is going to be stable very soon. Now, I want to hand it off to Juliet to talk about the fact that... Not every developer wants to be a security expert, right? Like, we've seen the current draft, now the new one that's about to go live into production, but not everyone, we have some exceptions here, who do want to become security experts.

You actually want to focus on building the remote MCP server, right? You want to solve a real problem. So, this is why the new authorization spec, and that's why Dan, why a bunch of people at Microsoft, we partnered with Anthropic in a security committee to get this new auth spec out there.

So, let's see if I paid attention. What are some of the core things that's going to change now moving forward? First of all, no need to implement the authorization servers anymore. So, that means we can now just rather than implementing it from scratch, we can actually attend it or append it to our server overall.

We can use the standard ways we only need to reference metadata that are going to point to our authorization servers. And there, that's where we're going to get the token. And then on server side, you're going to have the token, that information here. And all of this are still going to continue standard OAuth 2.0.

So, we can actually, as developers, we can rely on all of the libraries that are already out there, all of the services. So, it's going to make our lives a lot, a lot easier. What does this also include on client side? So, on client side, they are now, in a way, responsible for the end-to-end token dance.

So, this means if the authorization code comes in, we can validate it or the client validates, first of all, is the token, has it been acquired successfully? And then on server, it's going to pass it through to the server. And on server side, which is still very important, you're going to have to make sure if it's been validated correctly.

And also, of course, on server side, we have to implement the metadata, which I previously just talked about. So, again, a lot of enhancements now moving forward with the new spec. Saving effort. Saving keystrokes. As developers, they don't need to write a lot of security code because, again, the risk is higher.

Exactly. If you're not a security expert and you start implementing security code, what are the chances that you're going to get it right on the first shot? A hundred percent. And you can start relying on these off-shelf identity providers like Microsoft, Entra, Okta. So, all of these things. And you, it's just going to be less work for the developer.

But, yeah. How does it work in practice? Yeah. So, let's talk about, we talked about the new spec. And for folks that might be a little confused, like what the heck is the new spec and how exactly it works? So, in a new spec, there's a very clear separation of interaction between the MCP client, MCP server, and the authorization server.

So, in this case, what happens is your MCP client, like, let's say, Claude Desktop, is going to request data from the MCP server. The MCP server, at that point, because the MCP client doesn't have any user context yet, is going to respond back with a standard HTTP 401 saying, "I have no idea who you are, and my server is protected." But, here's a pointer to something that we call the PRM, the Protected Resource Metadata Document, that's embedded in one of the headers, in dot and dot authenticate, that's going to say, "But, you can go here and learn more about how to authorize against me, the MCP server." So, the MCP client, again, Claude Desktop, or VS Code, or any other variation, will then talk to the, take the PRM, extract from that PRM information about what authorization server it's using, whether it's Okta, Auth0, Entra, Keycloak, it doesn't really matter, and is going to then, again, I abstracted this out in a very simplistic way, step four, complete flow, but basically, the client is going to do the whole OAuth discovery, step by step, go through the dance, get the token, and then, it's going to request data with a token from the server, and the server's going to return it back.

The client is responsible for completing this entire OAuth dance, where the server now doesn't actually need to manage tokens, you only need to make sure that you're validating them. I call out this thing called the PRM, and the PRM is something hosted by the MCP server, that is essentially a JSON document, there's variation, it could be a JSON web token, but for the purpose of this conversation, it's basically a JSON document that says, hey, I am this resource, I am this server, and by the way, my authorization servers are the following, and you can give a list of servers, again, specify things like bare method supported, as well as scopes, so the client, when it gets this document, knows exactly how to bootstrap the end-to-end authorization flow with OAuth, again, standard OAuth, you can use, again, off-the-shelf libraries for doing this.

Let's eat an action in C#, and because we're Microsoft, of course, it's going to be C#, you know, so, this is currently in a, in a pull request for the C#, for the official MCP C# SDK, by the way, to show you just how easy it is to set up an MCP server that is protected by an OAuth provider, by an identity provider, I have essentially an ASP.NET Core application, it could work for any other application, but what I'm doing is, all I'm configuring is add authentication, to make sure that I'm actually adding auth to my server, I'm saying that it's using the MCP auth scheme, I'm adding some validation logic that, again, is built into the framework, oh, no, I see, I see what the problem is, I see, great call out, yeah, see, it's a fantastic demo, I'm going to duplicate my screen, that's, that's, I think, what it's going to do, there we go, all right, so, say it again, uh, I'm adding authentication, I'm adding MCP authentication defaults here, because it's all baked into the framework, I'm adding some logic to validate the JOT, the token, and this is, again, standard embedded into the framework components, uh, I have some metadata events that are relevant here, and then I'm saying add MCP, and within that MCP, I'm saying that I'm adding some PRM metadata that I just talked about, which is my server supporting header auth, and because I'm using EntraID, it can be, again, Okta, Auth0, I'll specify the metadata, and that's it, and then I'll say use authentication, use authorization, there's a lot of boilerplate code here, because it's an MCP server that uses, again, the stock SDK, but the auth, that's the complexity, that's all, I needed to add this metadata, and that's kind of it, when I start the server, so it's going to run locally, let's take this on, and what I'm going to do now is I'm going to go to the browser here, I'm going to refresh this, and you'll notice that this is the PRM that I talked about, I have a local host server, it says my authorization server is login to microsoftonline.com, because I'm using EntraID, again, it could be any of them, I define the scopes, and I say that it's using headers, that's it, that's what the server says to the client in terms of auth, now, I have another instance here, that is the client, and the client definition with the C# SDK, again, it's super, super simplistic, what I have here is, I'm essentially on the client side, saying that I'm using a generic auth provider, there's nothing Microsoft specific here, it's generic auth, I'm specifying the client ID for my MCP client, some scopes, and that's kind of it, the rest is standard boilerplate for transport setup, as you would with any other client, this client is already set up to connect to my test server, my local server, so if I run this, let's see, is it going to connect, it's going to go ahead and discover the metadata document, it actually went really fast, because I'm already authorized here, perfect demo, but behind the scenes that actually what it did is, it did request the token from EntraID, it verified, it sent the token to the server, the server verified it, and then invoked a tool that I had on the MCP server, and said that there's no alerts, it's a simple weather example, it's nothing too complex here, but the end-to-end developer experience here is extremely simple, like we worked very, very hard to not expose any of the security intricacies to developers, that's all you do, so C# SDK, it's there, it's in a PR, it's going to be in production very, very soon, so Julia, do you want to talk about VS Code and API management?

Yeah, totally, so okay, we saw this working locally now, we've used the libraries, so what if you now want to take it to production? I might be biased because I'm part of the Azure API management team, but I always recommend putting a gateway in between to make it more secure, and actually use it to protect and secure your remote MCP servers, and so what I'm going to show you today is, for this, we have a public available GitHub repository out there, and it's going to help you, and it's going to spin up an example, and in our example, let's scroll down and go to the overview here, and we're going to use Azure API management in the middle to do and help with authentication, and the beauty about this example is, it only uses an ACD app, so we wanted to give developers, especially, we've heard a lot of complaints about sometimes it takes some time, so we wanted to go super fast, so with an ACD app, it will spin up all of the resources.

So while I'm doing this, and everything is going to be deploying here, let's talk a little bit about what is going to be set up under the hood, and what's going to help make our remote MCP server more secure. So as I've mentioned, Azure API management as your remote MCP proxy, and we are hosting it, our remote MCP server on Azure, where we have three tools implemented.

We want to make sure the connection here is secured, and that's where we're going to use the gateway in between to help us do the dance, and for this, we have an OAuth API that's going to help the play between our identity provider. In our case, it's Microsoft EnterID.

That's going to help essentially with the login and also the content flow here to truly make sure that the connection here is secured to our backend, to our remote MCP server, right? All right. So let's see how the deployment of my resources are looking. I told you it truly only takes maybe five minutes max.

It does spin a bunch of other things like an app service plan, log analytics, to make sure that this is truly production ready, and it gives you a way to monitor and also analyze and log it. So I'm going to copy my endpoint here. Before I'm going to do something with it, let's just check on Azure API management side if all of the things have been implemented correctly, because what we should see now in my APIs tab is we should see the endpoint to my remote MCP server, which is the MCP API, and also the endpoint that's going to help us handle OAuth.

And of course, while the spec evolves, we are also going to evolve the samples and all of it that comes with it. So let's test it. I'm going to start MCP inspector here. And let's open MCP inspector and provide the URL endpoint. So once I connect, now what I should see is if I click the connect button here, this is going to pop up my content page, right?

So it's going to show the application name. It's going to make sure that I'm providing the right content. I'm going to allow access to it. The first time I'm doing it, I also have to provide the right permissions. So I'm going to accept this here. And once I'm back, now you can see I'm actually connected.

And now I'm going to list the tools. And as we talked about it, I currently just have three tools implemented here. All right. VS Code. How does it work actually now in VS Code, for example? VS Code has MCP support as well. I'm just going to provide the end point.

And I'm going to find a name for my MCP remote server here, which let's call it AI engineer. And it's going to add it to my user settings. And immediately it's going to start running it. And you can see now in VS Code, because they now also support OAuth, they're going to pop up the window.

They're going to show a notification about, hey, let's authenticate towards it. I'm going to open it. And we're going to see the same content page, right? This time with VS Code, different application name here, where we are again, we're going to provide our M content, we're going to allow it.

And now back, I'm authorized, I'm allowed to use it in VS Code Insider. So once that's done, you saw now I have access to the three tools here in VS Code. So let's test this, what it's going to do in Copilot Studio, GitHub Copilot. And so first, I'm going to select and see, perfect, it was able to select my tools, and it's able to detect these.

And now once I start interacting, I have my text prompt here, and just kind of do the hello worlds, and very simple example, and GitHub Copilot is now going to run it, it's going to detect the tool, because I've been authenticated, it's going to run it, and hopefully successfully, perfect.

And now we can also double check. So if I open the tool calling here, I can see that the output of Hello, I'm an MCP tool has been successfully provided. And something new, and I know the world is spinning very, very fast. So as being part of Azure API management, we want to make it easier as well.

So we know the similarities between MCP servers and APIs. So one of the latest announcements that we have done is, you can now also start transforming your REST APIs into remote MCP servers using our tools, using our platform here. And you can configure your already existing endpoint, REST endpoints, into tools that you want to expose to get like the VS code.

And we're going to do this all with our platform, because we want to make it easier for enterprise customers, but also developers to get started with this. So here in my use case, I just copied the endpoint that was provided by me by API management, I'm going to hit start and running.

And of course, always make sure to implement auth. And that's the beauty about our platform. You can use it for securing it, but also for hosting in this case. And now I'm able to also just immediately call it. And let's just check if GitHub Copilot was able to detect the MCP server here.

Perfect. You can see it right under my service AI engineering one. I'm seeing the three tools that is all based on my REST API in VS code. And now I'm ready to go and interact with it in VS code right here. With this being said, lots of things are changing in this space.

Any good words for the people out there who want to get started with remote MCP server then? Yeah. So there's links on the screen that you can go to. These are the specification documents that you can learn more about how MCP auth works. We also have a document that we partnered with Anthropic on.

It's called security best practices that outline what are the best practices you should be adopting in your MCP service. You want to make sure that you're not pawned. Very, very important. And then I'll also mention that starting with VS code insiders, we do support the new authorization spec. So you should check it out, download it, install it, give us your feedback.

And if anything doesn't work, we have Harold at this conference who can help you debug it. So thank you, folks. It's great. Stop by at the booth.