You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
title: Secure MCP servers with Microsoft Entra authentication
3
+
description: Configure Microsoft Entra authentication to secure your MCP server on Azure App Service and access it from Visual Studio Code.
4
+
ms.topic: how-to
5
+
ms.date: 11/18/2025
6
+
author: cephalin
7
+
ms.author: cephalin
8
+
ms.service: azure-app-service
9
+
ms.collection: ce-skilling-ai-copilot
10
+
ms.update-cycle: 180-days
11
+
---
12
+
13
+
# Secure Model Context Protocol calls to Azure App Service from Visual Studio Code with Microsoft Entra authentication
14
+
15
+
This article shows you how to secure your Model Context Protocol (MCP) server hosted on Azure App Service using Microsoft Entra authentication. By enabling authentication, you ensure that only users authenticated with Microsoft Entra can access your MCP server through Copilot agent mode in Visual Studio Code.
16
+
17
+
For other authentication methods and general MCP server security concepts, see [Secure a Model Context Protocol server in Azure App Service](configure-authentication-mcp.md).
18
+
19
+
## Prerequisites
20
+
21
+
An App Service app that hosts an MCP server. If you need to create one, see one of the following tutorials:
22
+
23
+
-[Integrate an App Service app as an MCP Server for GitHub Copilot Chat (.NET)](tutorial-ai-model-context-protocol-server-dotnet.md)
24
+
-[Integrate an App Service app as an MCP Server for GitHub Copilot Chat (Java)](tutorial-ai-model-context-protocol-server-java.md)
25
+
-[Integrate an App Service app as an MCP Server for GitHub Copilot Chat (Python)](tutorial-ai-model-context-protocol-server-python.md)
26
+
-[Integrate an App Service app as an MCP Server for GitHub Copilot Chat (Node.js)](tutorial-ai-model-context-protocol-server-node.md)
27
+
28
+
## Enable Microsoft Entra authentication
29
+
30
+
1. In the [Azure portal](https://portal.azure.com), navigate to your App Service app.
31
+
32
+
1. In the left menu, select **Settings** > **Authentication**, and then select **Add identity provider**.
33
+
34
+
1. On the **Add an identity provider** page, select **Microsoft** as the **Identity provider**.
35
+
36
+
1. Under **App Service authentication settings**, for **Client secret expiration**, select an expiration period (for example, **6 months**).
37
+
38
+
1. Accept all other default values and select **Add** to create the identity provider.
39
+
40
+
This creates a new app registration in Microsoft Entra ID with a client secret and configures your App Service app to use it for authentication.
41
+
42
+
## Authorize Visual Studio Code in App Service authentication
43
+
44
+
After enabling authentication, you need to authorize Visual Studio Code to access your MCP server.
45
+
46
+
1. On the **Authentication** page of your App Service app, under **Identity provider**, select **Edit** (the pencil icon) next to the Microsoft provider you created.
47
+
48
+
1. On the **Edit identity provider** page, under **Additional checks** > **Client application requirement**, select **Allow requests from specific client applications**.
49
+
50
+
1. Select the pencil widget to edit the allowed applications.
51
+
52
+
1. In the **Allowed client applications** field, add the Visual Studio Code client ID: `aebc6443-996d-45c2-90f0-388ff96faa56`.
53
+
54
+
1. Select **OK**, then select **Save**.
55
+
56
+
## Authorize Visual Studio Code in the app registration
57
+
58
+
Next, you need to configure the app registration to expose your API to Visual Studio Code.
59
+
60
+
1. Go back to the **Authentication** page of your App Service app.
61
+
62
+
1. Select the Microsoft provider in the **Identity provider** column to open the app registration page.
63
+
64
+
1. In the app registration page, select **Manage** > **Expose an API** from the left menu.
65
+
66
+
1. Under **Authorized client applications**, select **Add a client application**.
67
+
68
+
1. In the **Client ID** field, enter the Visual Studio Code client ID: `aebc6443-996d-45c2-90f0-388ff96faa56`.
69
+
70
+
1. Select the checkbox next to the **user_impersonation** scope to authorize this scope.
71
+
72
+
1. Select **Add application**.
73
+
74
+
1. Under **Scopes defined by this API**, find and copy the full scope value. It should look like `api://<app-registration-app-id>/user_impersonation`.
75
+
76
+
You need this scope value in the next section.
77
+
78
+
## Enable protected resource metadata by setting the authorization scope
79
+
80
+
To enable MCP server authorization, you need to configure the protected resource metadata (PRM) by setting the authorization scope in an app setting. This allows MCP clients to discover the authentication requirements through the `/.well-known/oauth-protected-resource` endpoint.
81
+
82
+
1. In the Azure portal, go back to your App Service app page.
83
+
84
+
1. In the left menu, select **Settings** > **Environment variables**.
85
+
86
+
1. Select **Add** to create a new application setting.
87
+
88
+
1. For **Name**, enter `WEBSITE_AUTH_PRM_DEFAULT_WITH_SCOPES`.
89
+
90
+
1. For **Value**, paste the scope you copied from the app registration: `api://<app-registration-app-id>/user_impersonation`.
91
+
92
+
1. Select **Apply**, then select **Apply** again to confirm and restart your app.
93
+
94
+
This setting configures the PRM to include the required scope for MCP server authorization.
95
+
96
+
## Connect from Visual Studio Code
97
+
98
+
Now you can connect to your secured MCP server from Visual Studio Code.
99
+
100
+
1. Open Visual Studio Code on your local machine.
101
+
102
+
1. Open or create an MCP configuration file (`mcp.json`). For a workspace scoped MCP configuration, create it in the *.vscode* directory of your workspace.
Replace `<your-app-url>` with your actual App Service app URL. You can find your app's default domain on the **Overview** page in the Azure portal. In this example, the path is `/api/mcp`, but the actual path depends on your MCP code.
118
+
119
+
1. In Visual Studio Code, open the Command Palette (`Ctrl+Shift+P` or `Cmd+Shift+P` on macOS).
120
+
121
+
1. Type **MCP: List Servers** and press Enter.
122
+
123
+
1. Select your MCP server from the list and choose **Start Server**.
124
+
125
+
1. Visual Studio Code automatically prompts you to sign in with Microsoft Entra ID. Follow the authentication prompts.
126
+
127
+
The MCP extension handles the OAuth flow using the scope you configured, and Visual Studio Code obtains the necessary access token to call your MCP server.
128
+
129
+
> [!TIP]
130
+
> If you see an unexpected authentication prompt or encounter errors, see [Troubleshooting](#troubleshooting).
131
+
132
+
1. Once authenticated, your MCP server is connected and ready to use in GitHub Copilot Chat agent mode or other MCP clients.
133
+
134
+
## Test the connection
135
+
136
+
To verify that your MCP server is properly secured and accessible:
137
+
138
+
1. Open GitHub Copilot Chat in Visual Studio Code (`Ctrl+Alt+I` or `Cmd+Option+I` on macOS).
139
+
140
+
1. Try using a feature from your MCP server. For example, if you're using the Todos sample:
141
+
142
+
```
143
+
Show me all my tasks
144
+
```
145
+
146
+
1. GitHub Copilot should successfully call your MCP server, and you should see the results in the chat. If you encounter any issues, see [Troubleshooting](#troubleshooting).
147
+
148
+
## Troubleshooting
149
+
150
+
When you start the MCP server in Visual Studio Code, the authentication prompt you see indicates whether your configuration is correct:
151
+
152
+
-**Correct configuration**: Visual Studio Code prompts you to **authenticate with Microsoft**. This means the protected resource metadata (PRM) is configured properly, and Visual Studio Code successfully discovered the authorization server and scope from the `/.well-known/oauth-protected-resource` endpoint.
153
+
154
+
-**Incorrect configuration**: Visual Studio Code prompts you to authenticate with an `/authorize` endpoint on your App Service app (for example, `https://<your-app-url>.azurewebsites.net/authorize`). This means the PRM is not configured properly. Visual Studio Code cannot find the authorization server and authorization scope, so it falls back to using your app's URL as the authorization endpoint, which doesn't exist.
155
+
156
+
If you see the incorrect authentication prompt, verify that:
157
+
- Your app setting `WEBSITE_AUTH_PRM_DEFAULT_WITH_SCOPES` is correctly configured with the full scope value `api://<app-registration-app-id>/user_impersonation`.
158
+
- The App Service app has fully restarted after adding the app setting. It might take a few minutes to complete the restart.
159
+
160
+
If you see authentication errors after signing in, verify that:
161
+
- The Visual Studio Code client ID (`aebc6443-996d-45c2-90f0-388ff96faa56`) is added to both the App Service authentication configuration (allowed client applications) and in the app registration (authorized client applications in **Expose an API**).
162
+
- The scope value in the app setting matches exactly what's defined in your app registration.
163
+
164
+
## Related content
165
+
166
+
-[Secure a Model Context Protocol server in Azure App Service](configure-authentication-mcp.md)
167
+
-[Configure your App Service or Azure Functions app to use Microsoft Entra sign-in](configure-authentication-provider-aad.md)
168
+
-[Configure the Microsoft Entra provider with a managed identity instead of a secret (preview)](configure-authentication-provider-aad.md#use-a-managed-identity-instead-of-a-secret-preview)
169
+
-[What is Model Context Protocol?](https://modelcontextprotocol.io/)
Copy file name to clipboardExpand all lines: articles/app-service/configure-language-python.md
+19-35Lines changed: 19 additions & 35 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -26,10 +26,7 @@ ms.custom:
26
26
27
27
This article describes how [Azure App Service](overview.md) runs Python apps, how you can migrate existing apps to Azure, and how you can customize the behavior of App Service when you need to. Python apps must be deployed with all the required [pip](https://pypi.org/project/pip/) modules.
28
28
29
-
The App Service deployment engine automatically activates a virtual environment and runs `pip install -r requirements.txt` when you deploy a [Git repository](deploy-local-git.md) or when you deploy a [zip package](deploy-zip.md)[with build automation enabled](deploy-zip.md#enable-build-automation-for-zip-deploy).
30
-
31
-
> [!NOTE]
32
-
> App Service currently requires `requirements.txt` in your project's root directory even if you have a `pyproject.toml`. See [Generate requirements.txt from pyproject.toml](#generate-requirementstxt-from-pyprojecttoml) for recommended approaches.
29
+
The App Service deployment engine automatically activates a virtual environment and installs dependencies from a `requirements.txt`, `pyproject.toml`, or `setup.py` file when you deploy a [Git repository](deploy-local-git.md) or when you deploy a [zip package](deploy-zip.md)[with build automation enabled](deploy-zip.md#enable-build-automation-for-zip-deploy).
33
30
34
31
This article provides key concepts and instructions for Python developers who use a built-in Linux container in App Service. If you've never used App Service, first complete the [Python quickstart](quickstart-python.md) and [Flask](tutorial-python-postgresql-app-flask.md), [Django](tutorial-python-postgresql-app-django.md), or [FastAPI](tutorial-python-postgresql-app-fastapi.md) with PostgreSQL tutorial.
35
32
@@ -84,7 +81,17 @@ The App Service build system, called Oryx, performs the following steps when you
84
81
85
82
1. Run a custom pre-build script, if that step is specified by the `PRE_BUILD_COMMAND` setting. (The script can itself run other Python and Node.js scripts, pip and npm commands, and Node-based tools like Yarn, for example, `yarn install` and `yarn build`.)
86
83
87
-
1. Run `pip install -r requirements.txt`. The *requirements.txt* file must be in the project's root folder. If it's not, the build process reports the error "Could not find setup.py or requirements.txt; Not running pip install."
84
+
1. Install dependencies. The build system checks for the following files in the project root:
- *pyproject.toml* with *poetry.lock*: Uses `poetry`.
88
+
- *pyproject.toml*: Uses `poetry`.
89
+
- *setup.py*: Runs `pip install .`.
90
+
91
+
> [!NOTE]
92
+
> If *pyproject.toml* is present but *uv.lock* is missing, App Service defaults to using Poetry, even if *poetry.lock* is also missing. To use `uv`, you must include *uv.lock* in your deployment.
93
+
94
+
If none of these files are found, the build process reports the error "Could not find setup.py or requirements.txt; Not running pip install."
88
95
89
96
1. If *manage.py* is found in the root of the repository (which indicates a Django app), run `manage.py collectstatic`. However, if the `DISABLE_COLLECTSTATIC` setting is `true`, this step is skipped.
90
97
@@ -112,36 +119,13 @@ For more information on how App Service runs and builds Python apps in Linux, se
112
119
> [!NOTE]
113
120
> Always use relative paths in all pre-build and post-build scripts because the build container in which Oryx runs is different from the runtime container in which the app runs. Never rely on the exact placement of your app project folder within the container (for example, that it's placed under *site/wwwroot*).
114
121
115
-
## Generate requirements.txt from pyproject.toml
116
-
117
-
Currently, App Service doesn't directly support `pyproject.toml`. If you use tools like Poetry or uv, the recommended approach is to generate a compatible *requirements.txt* file before deployment in your project's root:
118
-
119
-
### Using Poetry
120
-
121
-
Generate *requirements.txt* by using [Poetry](https://python-poetry.org/) with the [export plugin](https://github.com/python-poetry/poetry-plugin-export):
You can redeploy existing web applications to Azure as follows:
142
126
143
127
1. **Source repository**. Maintain your source code in a suitable repository, like GitHub, which enables you to set up continuous deployment later in this process.
144
-
- Your *requirements.txt* file must be at the root of your repository if you want App Service to automatically install the necessary packages.
128
+
- Your dependency file (such as *requirements.txt*, *pyproject.toml*, or *setup.py*) must be at the root of your repository if you want App Service to automatically install the necessary packages.
145
129
146
130
1. **Database**. If your app depends on a database, create the necessary resources on Azure as well.
147
131
@@ -248,9 +232,9 @@ This container has the following characteristics:
248
232
249
233
- By default, the base container image includes only the Flask web framework, but the container supports other frameworks that are WSGI-compliant and compatible with Python 3.6 and later, such as Django.
250
234
251
-
- To install other packages, such as Django, create a [*requirements.txt*](https://pip.pypa.io/en/stable/user_guide/#requirements-files) file in the root of your project that specifies your direct dependencies. App Service then installs those dependencies automatically when you deploy your project.
235
+
- To install other packages, such as Django, create a [*requirements.txt*](https://pip.pypa.io/en/stable/user_guide/#requirements-files), *pyproject.toml*, or *setup.py* file in the root of your project that specifies your direct dependencies. App Service then installs those dependencies automatically when you deploy your project.
252
236
253
-
The *requirements.txt*file must be in the project root or dependencies won't be installed. If this file isn't in the root, the build process reports the error "Could not find setup.py or requirements.txt; Not running pip install." If you encounter this error, check the location of your requirements file.
237
+
The dependency file must be in the project root or dependencies won't be installed. If this file isn't in the root, the build process reports the error "Could not find setup.py or requirements.txt; Not running pip install." If you encounter this error, check the location of your requirements file.
254
238
255
239
- App Service automatically defines an environment variable named `WEBSITE_HOSTNAME` that contains the web app's URL, such as `msdocs-hello-world.azurewebsites.net`. It also defines `WEBSITE_SITE_NAME`, which contains the name of your app, such as `msdocs-hello-world`.
256
240
@@ -403,7 +387,7 @@ Use the following steps to access the deployment logs:
403
387
1. On the **Logs** tab, select the **Commit ID** for the most recent commit.
404
388
1. On the **Log details** page that appears, select the **Show Logs** link that appears next to **Running oryx build**.
405
389
406
-
Build issues, like incorrect dependencies in*requirements.txt*and errors in pre-build or post-build scripts, appear in these logs. Errors also appear if your requirementsfile isn't named *requirements.txt* or doesn't appearin the root folder of your project.
390
+
Build issues, like incorrect dependencies in your dependency file and errors in pre-build or post-build scripts, appear in these logs. Errors also appear if your dependency file isn't found in the root folder of your project.
407
391
408
392
## Open SSH session in a browser
409
393
@@ -423,7 +407,7 @@ In general, the first step in troubleshooting is to use App Service diagnostics:
423
407
1. Select **Availability and Performance**.
424
408
1. Examine the information in **Application Logs**, **Container Crash**, and **Container Issues**, where the most common issues appear.
425
409
426
-
Next, examine both the [deployment logs](#access-deployment-logs) and the [app logs](#access-diagnostic-logs) for any error messages. These logs often identify specific issues that can prevent app deployment or app startup. For example, the build can fail if your *requirements.txt* file has the wrong file name or isn't present in your project root folder.
410
+
Next, examine both the [deployment logs](#access-deployment-logs) and the [app logs](#access-diagnostic-logs) for any error messages. These logs often identify specific issues that can prevent app deployment or app startup. For example, the build can fail if your dependency file isn't present in your project root folder.
427
411
428
412
The following sections provide guidance for specific issues.
429
413
@@ -459,9 +443,9 @@ The following sections provide guidance for specific issues.
459
443
460
444
#### Could not find setup.py or requirements.txt
461
445
462
-
-**The log stream shows "Could not find setup.py or requirements.txt; Not running pip install."** The Oryx build process failed to find your *requirements.txt*file.
446
+
-**The log stream shows "Could not find setup.py or requirements.txt; Not running pip install."** The Oryx build process failed to find your *requirements.txt*, *pyproject.toml*, or *setup.py* file.
463
447
464
-
- Connect to the web app's container via [SSH](#open-ssh-session-in-a-browser) and verify that *requirements.txt* is named correctly and exists directly under *site/wwwroot*. If it doesn't exist, make sure the file exists in your repository andis included in your deployment. If it exists in a separate folder, move it to the root.
448
+
- Connect to the web app's container via [SSH](#open-ssh-session-in-a-browser) and verify that your dependency file is named correctly and exists directly under *site/wwwroot*. If it doesn't exist, make sure the file exists in your repository and is included in your deployment. If it exists in a separate folder, move it to the root.
0 commit comments