Skip to content

Repo contains samples and instructions for remote hosting of MCP servers built with the official Anthropic MCP SDKs on Azure Functions.

License

Notifications You must be signed in to change notification settings

Azure-Samples/mcp-sdk-functions-hosting-python

Host remote MCP servers built with official MCP SDKs on Azure Functions (early preview)

This repo contains instructions and sample for running MCP server built with the Python MCP SDK on Azure Functions. The repo uses the weather sample server to demonstrate how this can be done. You can clone to run and test the server locally, follow by easy deploy with azd up to have it in the cloud in a few minutes.

Watch the video overview

Watch the video

Running MCP server as custom handler on Azure Functions

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:

Diagram showing hosting of Function app and custom handler apps.

Prerequisites

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.

If you already have an existing server...

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 Azure resources.

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:

  1. Inside the MCP server project, run azd init --template self-hosted-mcp-scaffold-python.
  2. Answer the prompts
    • Continue initializing an app in '/your/mcp/project/folder'?: Select Yes.
    • Files present both locally and in template: Likely the only one is README, and you can keep the existing.
    • Enter a unique environment name: This will become the name of the resource group the server is deployed in.
  3. In host.json:
    • Put the main Python script path as the value of arguments, e.g. weather.py
    • Ensure the port value is the same as the one used by the MCP server
  4. Follow instructions starting in the Test the server locally section.

You can find out more details about the template.

If you're starting from scratch...

Clone the repo and open the sample in Visual Studio Code

git clone https://github.com/Azure-Samples/mcp-sdk-functions-hosting-python.git

Test the server locally

Note

Oct 31 2025 update: Running the server locally requires Azure Functions Core Tools v4.5.0, which is not yet released. Skip to next section to prepare for deployment.

  1. In the root directory, run uv run func start to create the virtual environment, install dependencies, and start the server locally

  2. Open mcp.json (in the .vscode directory)

  3. Start the server by selecting the Start button above the local-mcp-server

  4. 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.

  5. Click the tools icon and make sure local-mcp-server is checked for Copilot to use in the chat:

    MCP tools list screenshot
  6. Once the server displays the number of tools available, ask "What is the weather in NYC?" Copilot should call one of the weather tools to help answer this question.

  7. Deactivate the virtual environment

Register resource provider before deploying

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

Deployment

  1. 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
  2. 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>
  3. 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/

Connect to server on Visual Studio Code

  1. Open mcp.json in the editor.
  2. Stop the local server by selecting the Stop button above the local-mcp-server.
  3. Start the remote server by selecting the Start button above the remote-mcp-server.
  4. Visual Studio Code will prompt you for the Function App name. Copy it from either the terminal output or the Portal.
  5. Open Copilot in Agent mode and make sure remote-mcp-server is checked in the tool's list.
  6. VS Code should prompt you to authenticate to Microsoft. Click Allow, and then login into your Microsoft account (the one used to access Azure Portal).
  7. Ask Copilot "What is the weather in Seattle?". It should call one of the weather tools to help answer.

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.

Log level screenshot

Redeployment

If you want to redeploy the server after making changes, there are different options:

  1. Run azd deploy. (See azd command reference.)
  2. Open command palette in Visual Studio Code (Command+Shift+P/Cntrl+Shift+P) and search for Azure Functions: Deploy to Function App. Then select the name of the function app to deploy to.

Built-in server authorization with Easy Auth

The server app is configured with Easy Auth, which implements the requirements of the MCP authorization specification, such as issuing 401 challenge and exposing a Protected Resource Metadata (PRM).

When the server is configured to use Easy Auth for MCP Server authorization, you should see the following sequence of events in the debug output from Visual Studio Code:

  1. The editor sends an initialization request to the MCP server.
  2. The MCP server responds with an error indicating that authorization is required. The response includes a pointer to the protected resource metadata (PRM) for the application. The Easy Auth feature generates the PRM for an app built with this sample.
  3. The editor fetches the PRM and uses it to identify the authorization server.
  4. The editor attempts to obtain authorization server metadata (ASM) from a well-known endpoint on the authorization server.
  5. Microsoft Entra ID doesn't support ASM on the well-known endpoint, so the editor falls back to using the OpenID Connect metadata endpoint to obtain the ASM. It tries to discover this using by inserting the well-known endpoint before any other path information.
  6. The OpenID Connect specifications actually defined the well-known endpoint as being after path information, and that is where Microsoft Entra ID hosts it. So the editor tries again with that format.
  7. The editor successfully retrieves the ASM. It then can then use this information in conjunction with its own client ID to perform a login. At this point, the editor prompts you to sign in and consent to the application.
  8. Assuming you successfully sign in and consent, the editor completes the login. It repeats the intialization request to the MCP server, this time including an authorization token in the request. This reattempt isn't visible at the Debug output level, but you can see it in the Trace output level.
  9. The MCP server validates the token and responds with a successful response to the initialization request. The standard MCP flow continues from this point, ultimately resulting in discovery of the MCP tool defined in this sample.

Support for other clients

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.

Clean up resources

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

Next steps

Find this sample in other languages

Language (Stack) Repo Location
C# (.NET) mcp-sdk-functions-hosting-dotnet
Node mcp-sdk-functions-hosting-node

Troubleshooting

The following are some common issues that come up.

  1. 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.

  2. 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.

  3. Need admin approval. Visual Studio Code needs permission to access resources in your organization that only an admin can grant. Please ask an admin to grant permission to this app before you can use it.

    This means your Entra app hasn't authorized VS Code as a trusted client. To fix this issue, go to the Azure Portal and search for your Entra app ("MCP Authorization App") in the global search bar. Inside the Entra app resource, click on Expose an API in the left menu. Look for the + Add a client application button. Click to add VS Code's Client ID aebc6443-996d-45c2-90f0-388ff96faa56, remembering to check the authorized scopes box and click Add application:

    Add VS Code client ID screenshot
  4. Connection state: Error Error sending message to {endpoint}: TypeError: fetch failed

    Ensure the Function app domain is correct when connecting to the server.

  5. Ensure you have the latest version of Azure Functions Core Tools installed.

    You need version >=4.4.0. Check by running func --version.

  6. .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.

About

Repo contains samples and instructions for remote hosting of MCP servers built with the official Anthropic MCP SDKs on Azure Functions.

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 5