Skip to content

This is a quickstart template to easily build and deploy a custom remote MCP server to the cloud using Azure functions. You can clone/restore/run on your local machine with debugging, and `azd up` to have it in the cloud in a couple minutes. The MCP server is secured by design using

License

Notifications You must be signed in to change notification settings

Azure-Samples/remote-mcp-functions-dotnet

Getting Started with Remote MCP Servers using Azure Functions (.NET/C#)

This is a quickstart template to easily build and deploy a custom remote MCP server to the cloud using Azure functions. You can clone/restore/run on your local machine with debugging, and azd up to have it in the cloud in a couple minutes.

The MCP server is configured with built-in authentication using Microsoft Entra as the identity provider.

You can also use API Management to secure the server, as well as network isolation using VNET.

Watch the video overview

Watch the video

If you're looking for this sample in more languages check out the Node.js/TypeScript and Python samples.

Open in GitHub Codespaces

Prerequisites

Required for all development approaches:

For Visual Studio development:

  • Visual Studio 2022
  • Make sure to select the Azure development workload during installation

For Visual Studio Code development:

Choose one: You can use either Visual Studio OR Visual Studio Code. Both provide full debugging support, but the setup steps differ slightly.

Below is the architecture diagram for the Remote MCP Server using Azure Functions:

Architecture Diagram

Prepare your local environment

An Azure Storage Emulator is needed for this particular sample because we will save and get snippets from blob storage. Start Azurite emulator:

docker run -p 10000:10000 -p 10001:10001 -p 10002:10002 \
    mcr.microsoft.com/azure-storage/azurite

Note if you use Azurite coming from VS Code extension you need to run Azurite: Start now or you will see errors.

Run your MCP Server locally

Choose your preferred development environment:

Option A: Using Visual Studio Code

Run from Terminal

  1. From the src folder, run this command to start the Functions host locally:

    cd src
    func start

Connect to your local MCP server from MCP client tools

Once your Azure Functions MCP server is running locally (via either Visual Studio Code or Visual Studio), you can connect to it from various MCP client tools:

Using VS Code with GitHub Copilot

  1. Open .vscode/mcp.json. Find the server called local-mcp-function and click Start above the name. The server is already set up with the running Function app's MCP endpoint:

    http://localhost:7071/runtime/webhooks/mcp

    Note: If you're running from Visual Studio (not VS Code), use http://localhost:7071/runtime/webhooks/mcp/sse instead.

  2. In Copilot chat agent mode enter a prompt to trigger the tool, e.g., select some code and enter this prompt

    Say Hello 
    
    Save this snippet as snippet1 
    
    Retrieve snippet1 and apply to NewFile.cs
    
  3. When prompted to run the tool, consent by clicking Continue

  4. When you're done, press Ctrl+C in the terminal window to stop the func.exe host process (or stop debugging in your IDE).

Using MCP Inspector

  1. In a new terminal window, install and run MCP Inspector

    npx @modelcontextprotocol/inspector
  2. CTRL click to load the MCP Inspector web app from the URL displayed by the app (e.g. http://0.0.0.0:5173/#resources)

  3. Set the transport type to Streamable HTTP

  4. Set the URL to your running Function app's MCP endpoint and Connect:

    http://0.0.0.0:7071/runtime/webhooks/mcp

    Note: If you're running from Visual Studio (not VS Code), use http://localhost:7071/runtime/webhooks/mcp/sse instead.

  5. List Tools. Click on a tool and Run Tool.

Troubleshooting Local Development

Problem: Connection refused when trying to connect to MCP server

  • Solution: Ensure Azurite is running (docker run -p 10000:10000 -p 10001:10001 -p 10002:10002 mcr.microsoft.com/azure-storage/azurite)

Problem: Wrong URL (0.0.0.0 vs localhost)

  • Solution: Use http://0.0.0.0:7071/runtime/webhooks/mcp for VS Code, http://localhost:7071/runtime/webhooks/mcp/sse for Visual Studio

Problem: Visual Studio F5 doesn't work

  • Solution: Ensure Azure development workload is installed and FunctionsMcpTool is set as startup project

Problem: The API version 2025-07-05 is not supported by Azurite

  • Solution: Pull the latest Azurite image (docker pull mcr.microsoft.com/azure-storage/azurite) then restart Azurite and the app.

Verify local blob storage in Azurite

After testing the snippet save functionality locally, you can verify that blobs are being stored correctly in your local Azurite storage emulator.

Using Azure Storage Explorer

  1. Open Azure Storage Explorer
  2. In the left panel, expand Emulator & AttachedStorage Accounts(Emulator - Default Ports) (Key)
  3. Navigate to Blob Containerssnippets
  4. You should see any saved snippets as blob files in this container
  5. Double-click on any blob to view its contents and verify the snippet data was saved correctly

Using Azure CLI (Alternative)

If you prefer using the command line, you can also verify blobs using Azure CLI with the storage emulator:

# List blobs in the snippets container
az storage blob list --container-name snippets --connection-string "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"
# Download a specific blob to view its contents
az storage blob download --container-name snippets --name <blob-name> --file <local-file-path> --connection-string "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"

This verification step ensures your MCP server is correctly interacting with the local storage emulator and that the blob storage functionality is working as expected before deploying to Azure.

Deploy to Azure for Remote MCP

Stop the local server with Ctrl+C.

Switch back to the root directory remote-mcp-functions-dotnet.

Sign in to Azure and initialize azd:

az login
azd auth login

Create a new azd project environment:

azd env new <environment-name>

We'll test the remote server with Visual Studio Code, so configure it as an allowed client application to request access tokens from Microsoft Entra:

azd env set PRE_AUTHORIZED_CLIENT_IDS aebc6443-996d-45c2-90f0-388ff96faa56

Run this azd command to provision the function app, with any required Azure resources, and deploy your code:

azd up

You can opt-in to a VNet being used in the sample. To do so, do this before azd up

azd env set VNET_ENABLED true

Connect to remote MCP server in Visual Studio Code - GitHub Copilot

Connect to the remote MCP server after deployment finishes. For GitHub Copilot within VS Code, use https://<funcappname>.azurewebsites.net/runtime/webhooks/mcp for the URL. Note a mcp.json is already included in this repo and will be picked up by VS Code, so just click Start above remote-mcp-function to be prompted for functionapp-name (in your azd command output or /.azure/*/.env file). You'll also be prompted to authenticate with Microsoft. Click Allow and login with your Azure subscription email.

Tip

Successful connect shows the number of tools the server has. You can see more details on the interactions between VS Code and server by clicking on More... -> Show Output above the server name.

{
    "inputs": [
        {
            "type": "promptString",
            "id": "functionapp-name",
            "description": "Azure Functions App Name"
        }
    ],
    "servers": {
        "remote-mcp-function": {
            "type": "http",
            "url": "https://${input:functionapp-name}.azurewebsites.net/runtime/webhooks/mcp",
        },
        "local-mcp-function": {
            "type": "http",
            "url": "http://localhost:7071/runtime/webhooks/mcp"
        }
    }
}

Redeploy your code

You can run the azd up command as many times as you need to both provision your Azure resources and deploy code updates to your function app.

Note

Deployed code files are always overwritten by the latest deployment package.

Clean up resources

When you're done working with your function app and related resources, you can use this command to delete the function app and its related resources from Azure and avoid incurring any further costs:

azd down

Source Code

The function code for the GetSnippet and SaveSnippet endpoints are defined in SnippetsTool.cs. The McpToolsTrigger attribute applied to the async Run method exposes the code function as an MCP Server.

The following shows the code for a few MCP server examples (get string, get object, save object):

[Function(nameof(GetSnippet))]
public object GetSnippet(
    [McpToolTrigger(GetSnippetToolName, GetSnippetToolDescription)] ToolInvocationContext context,
    [BlobInput(BlobPath)] string snippetContent)
{
    return snippetContent;
}

[Function(nameof(SaveSnippet))]
[BlobOutput(BlobPath)]
public string SaveSnippet(
    [McpToolTrigger(SaveSnippetToolName, SaveSnippetToolDescription)] ToolInvocationContext context,
    [McpToolProperty(SnippetNamePropertyName, PropertyType, SnippetNamePropertyDescription)] string name,
    [McpToolProperty(SnippetPropertyName, PropertyType, SnippetPropertyDescription)] string snippet)
{
    return snippet;
}

[Function(nameof(SayHello))]
public string SayHello(
    [McpToolTrigger(HelloToolName, HelloToolDescription)] ToolInvocationContext context
)
{
    logger.LogInformation("C# MCP tool trigger function processed a request.");
    return "Hello I am MCP Tool!";
}

Next Steps

About

This is a quickstart template to easily build and deploy a custom remote MCP server to the cloud using Azure functions. You can clone/restore/run on your local machine with debugging, and `azd up` to have it in the cloud in a couple minutes. The MCP server is secured by design using

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 13