logo
Free, unlimited AI code reviews that run on commit
git-lrc git-lrc GitHub Install Now We'd appreciate a star git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt

typescript-mcp-azure-functions-remote-server

Facilitates secure connection of client applications to a bespoke Model Context Protocol (MCP) backend hosted on Azure Functions, incorporating OAuth readiness and Virtual Network segmentation capabilities. The server deployment is streamlined for cloud management.

Author

typescript-mcp-azure-functions-remote-server logo

Azure-Samples

MIT License

Quick Info

GitHub GitHub Stars 41
NPM Weekly Downloads 0
Tools 1
Last Updated 2026-02-19

Tags

azurecloudmcpservices azureazure functionsusing azure

Deploying a Custom Remote MCP Endpoint via Azure Functions (TypeScript/Node.js)

This repository offers a rapid-start blueprint for deploying a personalized remote MCP backend utilizing Azure Function capabilities. Developers can clone, restore, and execute this solution locally with debugging support, and leverage azd up for cloud deployment in minutes. Security is paramount, enforced via cryptographic keys and HTTPS, with options for advanced OAuth integration using Azure EasyAuth or API Management, alongside network segregation via VNET.

Access Video Introduction Here

Alternative language implementations are available for .NET/C# and Python.

Open in GitHub Codespaces

The structural diagram for this Azure Functions-backed Remote MCP System is presented below:

Essential Prerequisites

Local Environment Setup

This specific template necessitates an Azure Storage Emulator to persist and retrieve code snippets from Azure Blob Storage.

  1. Initialize Azurite via Docker

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

Important: If you initiate Azurite through the VS Code extension, ensure you execute the Azurite: Start command manually, otherwise, errors will occur.

Executing the MCP Backend Locally via Terminal

  1. Install Required Packages shell npm install

  2. Compile the Source Code shell npm run build

  3. Launch the Functions Runtime Host: shell func start

By default, the endpoint utilized is the Server-Sent Events (SSE) route: /runtime/webhooks/mcp/sse. When deploying to Azure, authentication is managed via the query parameter: /runtime/webhooks/mcp/sse?code=<system_key>

Interacting with the Local MCP Backend from a Client Application

VS Code - Copilot Integration

  1. Open the Command Palette, select Add MCP Server, and input the SSE endpoint URL of your locally running Function app: shell http://0.0.0.0:7071/runtime/webhooks/mcp/sse

  2. Designate HTTP (Server-Sent-Events) as the MCP server protocol.

  3. Provide the aforementioned SSE endpoint URL.
  4. Assign a unique Server Identifier (any descriptive name).
  5. Specify configuration scope: User settings (global) or Workspace settings (local to this project).
  6. Invoke List MCP Servers from the Command Palette to initiate the configured server (this might happen automatically).
  7. In the Copilot chat interface, submit a prompt designed to invoke the tool, such as:

    plaintext Say Hello

    plaintext Save this snippet as snippet1

    plaintext Retrieve snippet1 and apply to newFile.ts 1. When prompted to execute the tool, confirm by clicking Continue. 1. Terminate the local host process by pressing Ctrl+C in the terminal running func.exe, and subsequently stop the MCP server via the List MCP Servers command.

Utilizing MCP Inspector

  1. In a new terminal instance, install and launch the MCP Inspector utility:

    shell npx @modelcontextprotocol/inspector node build/index.js

  2. If the Function app was previously halted, restart the host process:

shell func start

  1. Navigate to the MCP Inspector web interface by Control-clicking the URL displayed by the app (e.g., http://0.0.0.0:5173/#resources).
  2. Set the connection transport mechanism to SSE.
  3. Configure the URL field with your active Function app's SSE address and click Connect: shell http://0.0.0.0:7071/runtime/webhooks/mcp/sse
  4. Select List Tools. Choose the desired tool and execute Run Tool.

  5. To conclude, halt the func.exe host via Ctrl+C in its terminal, and then stop the @modelcontextprotocol/inspector process also using Ctrl+C.

Validation of Local Azurite Blob Storage Interaction

Following local testing of the snippet saving mechanism, confirm successful data persistence in your local Azurite emulator.

Using Azure Storage Explorer

  1. Launch Azure Storage Explorer.
  2. In the navigation pane, expand Emulator & AttachedStorage Accounts(Emulator - Default Ports) (Key).
  3. Browse to Blob Containerssnippets.
  4. All saved code snippets should appear as individual blob files in this container.
  5. Open any blob file to inspect its contents and confirm correct snippet data recording.

Verification via Azure CLI (Alternative Method)

For command-line verification, use the Azure CLI targeting the storage emulator:

# Enumerate blobs within 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;"
# Retrieve a specific blob for content inspection
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 phase ensures proper communication between the MCP backend and the local storage emulator prior to production deployment.

Cloud Deployment of the Remote MCP Endpoint

Optionally, you may choose to integrate a Virtual Network (VNet) into the deployment (this configuration must precede the azd up command):

azd env set VNET_ENABLED true

Execute the following azd command to provision all necessary Azure components, including the Function App, and deploy the code:

azd up

Note: Enhanced security and policy enforcement can be achieved via API Management, and preferred OAuth providers (like Entra ID) can be integrated using the [App Service built-in authentication]https://learn.microsoft.com/en-us/azure/app-service/overview-authentication-authorization).

Connecting to the Deployed Remote MCP Endpoint

The client application requires the system key to authorize invocation of the deployed SSE endpoint, which follows the format: https://<funcappname>.azurewebsites.net/runtime/webhooks/mcp/sse. By default, the hosted function mandates a system key, obtainable either via the [Azure Portal]https://learn.microsoft.com/en-us/azure/azure-functions/function-keys-how-to?tabs=azure-portal) or the CLI (az functionapp keys list --resource-group <resource_group> --name <function_app_name>). Retrieve the system key specifically named mcp_extension.

Remote Connection within MCP Inspector

The key can be appended directly to the URL:

https://<funcappname>.azurewebsites.net/runtime/webhooks/mcp/sse?code=<your-mcp-extension-system-key>

Remote Connection within VS Code - GitHub Copilot Setup

For GitHub Copilot in VS Code, the key must be transmitted as the x-functions-key header within the mcp.json configuration file, while the URL remains: https://<funcappname>.azurewebsites.net/runtime/webhooks/mcp/sse. The configuration below demonstrates how the included mcp.json prompts for the key upon server startup:

{
    "inputs": [
        {
            "type": "promptString",
            "id": "functions-mcp-extension-system-key",
            "description": "Azure Functions MCP Extension System Key",
            "password": true
        },
        {
            "type": "promptString",
            "id": "functionapp-name",
            "description": "Azure Functions App Name"
        }
    ],
    "servers": {
        "remote-mcp-function": {
            "type": "sse",
            "url": "https://${input:functionapp-name}.azurewebsites.net/runtime/webhooks/mcp/sse",
            "headers": {
                "x-functions-key": "${input:functions-mcp-extension-system-key}"
            }
        },
        "local-mcp-function": {
            "type": "sse",
            "url": "http://0.0.0.0:7071/runtime/webhooks/mcp/sse"
        }
    }
}
  1. Initiate the server configuration named remote-mcp-function within the mcp.json file by clicking Start.

  2. When prompted by VS Code, supply the name of the function application deployed to Azure.

  3. Input the acquired Azure Functions MCP Extension System Key in response to the prompt. This key can be retrieved from the Azure portal under the Function app's Functions menu, specifically in App Keys, copying the value associated with mcp_extension under System Keys.

  4. In Copilot chat mode, enter a prompt to activate the tool, for example:

    plaintext Say Hello

    plaintext Save this snippet as snippet1

    plaintext Retrieve snippet1 and apply to newFile.ts

Redeployment Procedures

You can execute azd up repeatedly to manage both the initial provisioning of Azure infrastructure and subsequent deployment of code modifications to your Function App.

[!NOTE] All deployed file contents are superseded by the latest deployment package.

Resource Decommissioning

Upon concluding work with the Function App and associated infrastructure, execute the following command to dismantle the function app and all dependent resources in Azure, thereby eliminating ongoing charges:

azd down

Source Code Details

The core logic for the getSnippet and saveSnippet service routes resides within the TypeScript modules located in the src directory. The MCP function decorators expose these underlying functions as callable tools for the remote server.

Below are examples of the TypeScript implementation for several MCP server operations (fetching/saving string data, fetching/saving object structures):

// Implementation for the Hello function - returns a standardized greeting
export async function mcpToolHello(context: InvocationContext): Promise<string> {
    return "Hello I am MCP Tool!";
}

// Registration of the 'hello' tool
app.mcpTool('hello', {
    toolName: 'hello',
    description: 'Simple hello world MCP Tool that responses with a hello message.',
    handler: mcpToolHello
});

// Implementation for GetSnippet - retrieves stored content by identifier
export async function getSnippet(_message: unknown, context: InvocationContext): Promise<string> {
    console.info('Getting snippet');

    // Extract snippet name from tool arguments metadata
    const mcptoolargs = context.triggerMetadata.mcptoolargs as { snippetname?: string };
    const snippetName = mcptoolargs?.snippetname;

    console.info(`Snippet name: ${snippetName}`);

    if (!snippetName) {
        return "No snippet name provided";
    }

    // Retrieve content from the blob binding (via extraInputs)
    const snippetContent = context.extraInputs.get(blobInputBinding);

    if (!snippetContent) {
        return `Snippet '${snippetName}' not found`;
    }

    console.info(`Retrieved snippet: ${snippetName}`);
    return snippetContent as string;
}


// Registration of the GetSnippet tool
app.mcpTool('getsnippet', {
    toolName: GET_SNIPPET_TOOL_NAME,
    description: GET_SNIPPET_TOOL_DESCRIPTION,
    toolProperties: [
        {
            propertyName: SNIPPET_NAME_PROPERTY_NAME,
            propertyValue: PROPERTY_TYPE,
            description: SNIPPET_NAME_PROPERTY_DESCRIPTION,
        }
    ],
    extraInputs: [blobInputBinding],
    handler: getSnippet
});

// Implementation for SaveSnippet - persists content under a given name
export async function saveSnippet(_message: unknown, context: InvocationContext): Promise<string> {
    console.info('Saving snippet');

    // Extract snippet name and content from tool arguments
    const mcptoolargs = context.triggerMetadata.mcptoolargs as { 
        snippetname?: string;
        snippet?: string;
    };

    const snippetName = mcptoolargs?.snippetname;
    const snippet = mcptoolargs?.snippet;

    if (!snippetName) {
        return "No snippet name provided";
    }

    if (!snippet) {
        return "No snippet content provided";
    }

    // Commit the snippet to blob storage via the output binding
    context.extraOutputs.set(blobOutputBinding, snippet);

    console.info(`Saved snippet: ${snippetName}`);
    return snippet;
}

// Registration of the SaveSnippet tool
app.mcpTool('savesnippet', {
    toolName: SAVE_SNIPPET_TOOL_NAME,
    description: SAVE_SNIPPET_TOOL_DESCRIPTION,
    toolProperties: [
        {
            propertyName: SNIPPET_NAME_PROPERTY_NAME,
            propertyValue: PROPERTY_TYPE,
            description: SNIPPET_NAME_PROPERTY_DESCRIPTION,
        },
        {
            propertyName: SNIPPET_PROPERTY_NAME,
            propertyValue: PROPERTY_TYPE,
            description: SNIPPET_PROPERTY_DESCRIPTION,
        }
    ],
    extraOutputs: [blobOutputBinding],
    handler: saveSnippet
});

Crucially, the host.json configuration file must reference the experimental extension bundle, which is a dependency for utilizing this feature set:

"extensionBundle": {
  "id": "Microsoft.Azure.Functions.ExtensionBundle.Experimental",
  "version": "[4.*, 5.0.0)"
}

Subsequent Actions

  • Integrate API Management as a gateway for your MCP backend (security policies, traffic routing, etc.).
  • Secure the MCP server using the [built-in authentication]https://learn.microsoft.com/en-us/azure/app-service/overview-authentication-authorization) features.
  • Activate VNET integration by setting the VNET_ENABLED=true flag.
  • Investigate further resources related to [Microsoft's MCP initiatives]https://github.com/microsoft/mcp/tree/main/Resources)

WIKIPEDIA CONTEXT:

Cloud computing, as defined by ISO, represents "a paradigm for enabling network access to a scalable and elastic pool of shareable physical or virtual resources with self-service provisioning and administration on-demand." This concept is widely known as "the cloud."

== Key Attributes ==

In 2011, the U.S. National Institute of Standards and Technology (NIST) formalized five "essential characteristics" for cloud environments. These definitions include:

  1. On-demand self-service: Consumers gain the ability to unilaterally procure computing resources (like server capacity or network storage) automatically, without requiring direct intervention from the service provider.
  2. Broad network access: Services must be accessible over standard network protocols, supporting a wide array of client devices (e.g., mobile, desktop).
  3. Resource pooling: Provider resources are aggregated for multi-tenant usage, dynamically allocating and reallocating infrastructure based on fluctuating consumer requirements.
  4. Rapid elasticity: Capabilities can be scaled up or down, sometimes automatically, to match demand swiftly. To the user, these resources appear limitless and instantly available.
  5. Measured service: Resource consumption (storage, processing, bandwidth) is automatically tracked and optimized at an appropriate abstraction layer, ensuring transparent usage reporting for both provider and consumer.

These criteria have since undergone refinement by the International Organization for Standardization (ISO) as of 2023.

== Historical Development ==

The genesis of cloud computing traces back to the 1960s, marked by the emergence of time-sharing concepts, often facilitated by Remote Job Entry (RJE). During this period, mainframe utilization relied heavily on the "data center" model, where user jobs were managed by system operators. The focus was on experimenting with methods to maximize access to large-scale computation via time-sharing, thereby boosting infrastructure efficiency and end-user output.

The visual cloud metaphor for delivering virtualized services originated in 1994, employed by General Magic to denote the virtual space reachable by agents within their Telescript framework. This attribution is often given to David Hoffman, a communications specialist at General Magic, who adapted it from its existing use in telecommunications networking. The term "cloud computing" gained wider recognition in 1996 when Compaq Computer Corporation drafted a strategic business plan centered around the Internet and future computing architecture, signaling an ambitious step towards...

See Also

`