This repo contains instructions and sample for running MCP server built with the Python MCP SDK on Azure Functions. The repo include a sample server demonstrate various MCP tools.
You can clone to run and test the servers locally, then easily deploy with azd up to have them in the cloud in a few minutes.
Watch the video overview
Recently Azure Functions released the Functions MCP extension, allowing developers to build MCP servers using Functions programming model, which is essentially Function's event-driven framework, and host them remotely on the serverless platform.
For those who have already built servers with Anthropic's MCP SDKs, it's also possible to host the servers on Azure Functions by running them as custom handlers, which are lightweight web servers that receive events from the Functions host. They allow you to host your already-built MCP servers with no code changes and benefit from Function's bursty scale, serverless pricing model, and security features.
This repo focuses on the second hosting scenario:
Ensure you have the following:
[!NOTE] This sample requires that you have permission to create a Microsoft Entra app in the Azure subscription you use.
[!IMPORTANT] Your server must be stateless and uses the streamable-http transport to be hosted remotely on Azure Functions today.
The following instructions will pull in artifacts required for local server testing and deployment. The most important are: host.json, local.settings.json, and infra. Azure Functions only requires the first two JSON files. The infra directory isn't a requirement, but it's handy for provisioning and deploying the server.
It's unlikely that your project would have files and directory with the same names, but if it does, you'll need to rename them so they won't be overwritten.
Once you've done the necessary renaming, follow these steps:
azd init --template self-hosted-mcp-scaffold-python.host.json:
arguments, e.g. weather.pyport value is the same as the one used by the MCP serverYou can find out more details about the template.
Clone the repo and open the sample in Visual Studio Code
git clone https://github.com/Azure-Samples/mcp-sdk-functions-hosting-python.git
In the root directory, run uv run func start to create the virtual environment, install dependencies, and start the server locally
Open mcp.json (in the .vscode directory)
Start the server by selecting the Start button above the local-mcp-server
Click on the Copilot icon at the top to open chat (or Ctrl+Command+I / Ctrl+Alt+I), and then change to Agent mode in the question window.
Click the tools icon and make sure local-mcp-server is checked for Copilot to use in the chat:
Once the server displays the number of tools available, ask "Return the weather in NYC using #local-mcp-server" Copilot should call one of the weather tools to help answer this question.
Deactivate the virtual environment
[!NOTE] When the server starts locally, the Azure Functions host first pings the root (
/) to ensure the app is up and running. Since the root isn't implemented, a 404 is returned.Info logs coming from the MCP SDK may be written to stderr by default, which is why they appear red in Azure Functions.
Before deploying, you need to register the Microsoft.App resource provider:
az provider register --namespace 'Microsoft.App'
Wait a few seconds for registration to complete. You can check status by using:
az provider show -n Microsoft.App
This sample uses Visual Studio Code as the main client. Configure it as an allowed client application:
azd env set PRE_AUTHORIZED_CLIENT_IDS aebc6443-996d-45c2-90f0-388ff96faa56
Specify a service management reference if required by your organization. If you're not a Microsoft employee and don't know that you need to set this, you can skip this step. However, if provisioning fails with an error about a missing service management reference, you may need to revisit this step. Microsoft employees using a Microsoft tenant must provide a service management reference (your Service Tree ID). Without this, you won't be able to create the Entra app registration, and provisioning will fail.
azd env set SERVICE_MANAGEMENT_REFERENCE <service-management-reference>
Run azd up in the root directory. Then pick an Azure subcription to deploy resources to and select from the available regions.
When the deployment finishes, your terminal will display output similar to the following:
(✓) Done: Resource group: rg-resource-group-name (12.061s)
(✓) Done: App Service plan: plan-random-guid (6.748s)
(✓) Done: Virtual Network: vnet-random-guid (8.566s)
(✓) Done: Log Analytics workspace: log-random-guid (29.422s)
(✓) Done: Storage account: strandomguid (34.527s)
(✓) Done: Application Insights: appi-random-guid (8.625s)
(✓) Done: Function App: func-mcp-random-guid (36.096s)
(✓) Done: Private Endpoint: blob-private-endpoint (30.67s)
Deploying services (azd deploy)
(✓) Done: Deploying service api
- Endpoint: https://functionapp-name.azurewebsites.net/
[!TIP] In addition to starting an MCP server in mcp.json, you can see output of a server by clicking More... -> Show Output. The output provides useful information like why a connection might've failed.
You can also click the gear icon to change log levels to "Traces" to get even more details on the interactions between the client (Visual Studio Code) and the server.
![]()
The get_user_info tool demonstrates how to implement the On-Behalf-Of (OBO) flow to call Microsoft Graph API on behalf of the authenticated user. This pattern is useful when your MCP tools need to access downstream services.
To test this tool, ask Copilot a question like "Use #remote-mcp-server to provide info abou the logged-in user". Copilot will ask you to provide consent to access the user's information by giving you a link. Navigate to the consent URL and grant the permissions. Then re-ask the question to Copilot.
Authorization headerOnBehalfOfCredential exchanges the bearer token for a Microsoft Graph access token/me endpoint with the exchanged tokenNote: This tool requires the infrastructure to be deployed to Azure. It will not work in local development without additional configuration.
If you want to redeploy the server after making changes, run azd deploy. (See azd command reference.)
The server app is configured with the built-in server authentication and authorization feature, which implements the requirements of the MCP authorization specification, such as issuing 401 challenge and exposing a Protected Resource Metadata (PRM).
In the debug output from Visual Studio Code, you see a series of requests and responses as the MCP client and server interact. When built-in MCP server authorization is used, you should see the following sequence of events:
Other than Visual Studio Code, agents in Azure AI Foundry can also connect to Function-hosted MCP servers that are configured with Easy Auth. Docs coming soon.
When you're done working with your server, you can use this command to delete the resources created on Azure and avoid incurring any further costs:
azd down
| Language (Stack) | Repo Location |
|---|---|
| C# (.NET) | mcp-sdk-functions-hosting-dotnet |
| Node | mcp-sdk-functions-hosting-node |
The following are some common issues that come up.
InternalServerError: There was an unexpected InternalServerError. Please try again later.
Check if you have registered the Microsoft.App resource provider:
az provider show -n Microsoft.App
If it's showing up as unregistered, register it:
az provider register --namespace 'Microsoft.App'
Successful registration should show:
Namespace RegistrationPolicy RegistrationState
------------- -------------------- -------------------
Microsoft.App RegistrationRequired Registered
Then run azd up again.
Error: error executing step command 'deploy --all': getting target resource: resource not found: unable to find a resource tagged with 'azd-server-name: api'. Ensure the service resource is corrected tagged in your infrastructure configuration, and rerun provision
This is a known transient error. Try re-running azd up.
Ensure you have the latest version of Azure Functions Core Tools installed.
You need version >=4.5.0. Check by running func --version.
.vscode/mcp.json must be in the root for VS Code to detect MCP server registration
If you don't see the Start button above server registrations, it's likely because .vscode/mcp.json isn't located in the root of your workspace folder.
Bicep
81.1%
Python
16.3%
HTML
2.6%
This repo contains instructions and sample for running MCP server built with the Python MCP SDK on Azure Functions. The repo include a sample server demonstrate various MCP tools.
You can clone to run and test the servers locally, then easily deploy with azd up to have them in the cloud in a few minutes.
Watch the video overview
Recently Azure Functions released the Functions MCP extension, allowing developers to build MCP servers using Functions programming model, which is essentially Function's event-driven framework, and host them remotely on the serverless platform.
For those who have already built servers with Anthropic's MCP SDKs, it's also possible to host the servers on Azure Functions by running them as custom handlers, which are lightweight web servers that receive events from the Functions host. They allow you to host your already-built MCP servers with no code changes and benefit from Function's bursty scale, serverless pricing model, and security features.
This repo focuses on the second hosting scenario:
Ensure you have the following:
[!NOTE] This sample requires that you have permission to create a Microsoft Entra app in the Azure subscription you use.
[!IMPORTANT] Your server must be stateless and uses the streamable-http transport to be hosted remotely on Azure Functions today.
The following instructions will pull in artifacts required for local server testing and deployment. The most important are: host.json, local.settings.json, and infra. Azure Functions only requires the first two JSON files. The infra directory isn't a requirement, but it's handy for provisioning and deploying the server.
It's unlikely that your project would have files and directory with the same names, but if it does, you'll need to rename them so they won't be overwritten.
Once you've done the necessary renaming, follow these steps:
azd init --template self-hosted-mcp-scaffold-python.host.json:
arguments, e.g. weather.pyport value is the same as the one used by the MCP serverYou can find out more details about the template.
Clone the repo and open the sample in Visual Studio Code
git clone https://github.com/Azure-Samples/mcp-sdk-functions-hosting-python.git
In the root directory, run uv run func start to create the virtual environment, install dependencies, and start the server locally
Open mcp.json (in the .vscode directory)
Start the server by selecting the Start button above the local-mcp-server
Click on the Copilot icon at the top to open chat (or Ctrl+Command+I / Ctrl+Alt+I), and then change to Agent mode in the question window.
Click the tools icon and make sure local-mcp-server is checked for Copilot to use in the chat:
Once the server displays the number of tools available, ask "Return the weather in NYC using #local-mcp-server" Copilot should call one of the weather tools to help answer this question.
Deactivate the virtual environment
[!NOTE] When the server starts locally, the Azure Functions host first pings the root (
/) to ensure the app is up and running. Since the root isn't implemented, a 404 is returned.Info logs coming from the MCP SDK may be written to stderr by default, which is why they appear red in Azure Functions.
Before deploying, you need to register the Microsoft.App resource provider:
az provider register --namespace 'Microsoft.App'
Wait a few seconds for registration to complete. You can check status by using:
az provider show -n Microsoft.App
This sample uses Visual Studio Code as the main client. Configure it as an allowed client application:
azd env set PRE_AUTHORIZED_CLIENT_IDS aebc6443-996d-45c2-90f0-388ff96faa56
Specify a service management reference if required by your organization. If you're not a Microsoft employee and don't know that you need to set this, you can skip this step. However, if provisioning fails with an error about a missing service management reference, you may need to revisit this step. Microsoft employees using a Microsoft tenant must provide a service management reference (your Service Tree ID). Without this, you won't be able to create the Entra app registration, and provisioning will fail.
azd env set SERVICE_MANAGEMENT_REFERENCE <service-management-reference>
Run azd up in the root directory. Then pick an Azure subcription to deploy resources to and select from the available regions.
When the deployment finishes, your terminal will display output similar to the following:
(✓) Done: Resource group: rg-resource-group-name (12.061s)
(✓) Done: App Service plan: plan-random-guid (6.748s)
(✓) Done: Virtual Network: vnet-random-guid (8.566s)
(✓) Done: Log Analytics workspace: log-random-guid (29.422s)
(✓) Done: Storage account: strandomguid (34.527s)
(✓) Done: Application Insights: appi-random-guid (8.625s)
(✓) Done: Function App: func-mcp-random-guid (36.096s)
(✓) Done: Private Endpoint: blob-private-endpoint (30.67s)
Deploying services (azd deploy)
(✓) Done: Deploying service api
- Endpoint: https://functionapp-name.azurewebsites.net/
[!TIP] In addition to starting an MCP server in mcp.json, you can see output of a server by clicking More... -> Show Output. The output provides useful information like why a connection might've failed.
You can also click the gear icon to change log levels to "Traces" to get even more details on the interactions between the client (Visual Studio Code) and the server.
![]()
The get_user_info tool demonstrates how to implement the On-Behalf-Of (OBO) flow to call Microsoft Graph API on behalf of the authenticated user. This pattern is useful when your MCP tools need to access downstream services.
To test this tool, ask Copilot a question like "Use #remote-mcp-server to provide info abou the logged-in user". Copilot will ask you to provide consent to access the user's information by giving you a link. Navigate to the consent URL and grant the permissions. Then re-ask the question to Copilot.
Authorization headerOnBehalfOfCredential exchanges the bearer token for a Microsoft Graph access token/me endpoint with the exchanged tokenNote: This tool requires the infrastructure to be deployed to Azure. It will not work in local development without additional configuration.
If you want to redeploy the server after making changes, run azd deploy. (See azd command reference.)
The server app is configured with the built-in server authentication and authorization feature, which implements the requirements of the MCP authorization specification, such as issuing 401 challenge and exposing a Protected Resource Metadata (PRM).
In the debug output from Visual Studio Code, you see a series of requests and responses as the MCP client and server interact. When built-in MCP server authorization is used, you should see the following sequence of events:
Other than Visual Studio Code, agents in Azure AI Foundry can also connect to Function-hosted MCP servers that are configured with Easy Auth. Docs coming soon.
When you're done working with your server, you can use this command to delete the resources created on Azure and avoid incurring any further costs:
azd down
| Language (Stack) | Repo Location |
|---|---|
| C# (.NET) | mcp-sdk-functions-hosting-dotnet |
| Node | mcp-sdk-functions-hosting-node |
The following are some common issues that come up.
InternalServerError: There was an unexpected InternalServerError. Please try again later.
Check if you have registered the Microsoft.App resource provider:
az provider show -n Microsoft.App
If it's showing up as unregistered, register it:
az provider register --namespace 'Microsoft.App'
Successful registration should show:
Namespace RegistrationPolicy RegistrationState
------------- -------------------- -------------------
Microsoft.App RegistrationRequired Registered
Then run azd up again.
Error: error executing step command 'deploy --all': getting target resource: resource not found: unable to find a resource tagged with 'azd-server-name: api'. Ensure the service resource is corrected tagged in your infrastructure configuration, and rerun provision
This is a known transient error. Try re-running azd up.
Ensure you have the latest version of Azure Functions Core Tools installed.
You need version >=4.5.0. Check by running func --version.
.vscode/mcp.json must be in the root for VS Code to detect MCP server registration
If you don't see the Start button above server registrations, it's likely because .vscode/mcp.json isn't located in the root of your workspace folder.
Bicep
81.1%
Python
16.3%
HTML
2.6%