Build and Deploy a Remote MCP Server with Azure Functions in 10 Minutes
Discover how to create a remote MCP server that can plug into your AI systems and add significant additional functionality. This article explains how to get an MCP server running locally using Azure Functions tools, deploy it to Azure, and integrate it with GitHub Copilot in VS Code for powerful custom interactions.
For this guide, we will be using TypeScript. You can find the necessary resources and code for other languages at aka.ms/mcp-remote
. After cloning the repository, open the readme file to get started.
What is an MCP Server?
An MCP server is essentially a collection of tools, much like a utility belt for your AI systems. While AI models have a vast knowledge base, they are unaware of your personal or company-specific APIs. MCP (Microsoft Copilot Platform) tools bridge this gap.
Tools like hello
, get snippet
, save snippet
, and argument handlers can augment an MCP client, such as VS Code with GitHub Copilot, to perform custom actions.
Running the Server Locally in 5 Simple Steps
To run the server on your local machine, you'll need to follow a few setup steps.
- Start the Azure Storage Emulator: You can run a Docker command or use the VS Code extension to start the Azure storage emulator.
- Install Function Extensions: At the root of the project, run the following command:
bash func extensions install
- Install Dependencies: Install the necessary npm packages.
bash npm install
- Build the Project: Compile the TypeScript code.
bash npm run build
- Start the Local Server: Launch the Azure functions locally.
bash func start
Testing with the MCP Inspector
To test the local server, you need an MCP client. The MCP Inspector
is a convenient tool for this purpose. Run the command provided in the repository to get a URL for the inspector.
Once the inspector is open, switch from the default "standard input/output" to "server-side events" to connect to the Azure Functions host. The URL for your running function will be something like runtime/webhooks/mcp/serversideevents
.
After connecting, you can list and test the available tools:
- hello
: A basic tool that echoes a greeting.
- get snippet
: Retrieves a stored snippet. If you request a snippet named "foo" without saving one first, it will correctly report that it wasn't found.
- save snippet
: Saves a piece of text. For example, you can save a snippet named "foo" with the content "this is my text to save". Subsequently, running get snippet
for "foo" will return the saved text.
This local testing setup is excellent for development but doesn't involve an LLM yet.
Deploying to Azure Functions
Deploying the function to the cloud provides scalability and accessibility. The deployment can be handled with a single command.
az functionapp up
You will be prompted to select your Azure subscription and a region for deployment. Once the process is complete, your function will be live.
Note: After deployment, navigate to your function in the Azure portal. Under App Keys, you will find an MCP extension
value. This key is intended for development and testing purposes only and should not be used in production.
You can test the deployed function by constructing a URL with your function's domain and the key: https://<your-function-domain>/...&code=<your-mcp-extension-key>
. Pasting this into a browser should yield a response, confirming it's active. This URL can also be used with the MCP Inspector to test the cloud-hosted version.
A Look at the Tools' Code
The core logic resides within the src
folder.
index.ts
: This file sets up the application to enable HTTP streaming.- Function Files: Each function has its own file containing the specific logic.
The hello
Tool
The simplest tool is MCP tool hello
, which just writes out "hello I am MCP tool". It is registered as an MCP tool using app.mcp.tool
, as shown below. The name
and description
are crucial, as the description informs the AI system when to invoke the tool.
app.mcp.tool('hello', {
description: 'A simple tool that says hello.',
handler: async (context) => {
context.stream.write('hello I am MCP tool');
}
});
Handling Arguments
For tools that require arguments, the invocationContext
is used. In the arguments example, the tool expects latitude
and longitude
. These arguments are accessed via context.triggerMetadata.mcp.tool.args
.
To ensure the AI system knows what parameters to extract from a user's prompt, the tool's properties are defined during registration. This can be done in two ways:
- Direct Object Definition: Manually define the properties object.
- Using the Zod Library: A more robust method using Zod to define the schema, which is often preferred in TypeScript projects.
// Zod example for tool properties
const locationSchema = z.object({
latitude: z.number().describe('The latitude'),
longitude: z.number().describe('The longitude'),
});
The Snippets Tool
The snippets tool demonstrates interaction with external services, in this case, Azure Blob Storage.
- get snippet
: Retrieves a snippet by name from blob storage. It requires the snippetName
as an argument.
- save snippet
: Saves a snippet, requiring both a name
and the text
content as arguments, and then stores it in blob storage.
Integrating with VS Code and GitHub Copilot
To register the remote MCP server in VS Code:
- Open the command palette (
Ctrl+Shift+P
orCmd+Shift+P
). - Type
MCP
and select MCP: Add Server. - Choose Server-Side Events and enter the URL of your deployed Azure Function.
- Give the server a name and add it to your user settings for global availability.
This will add a configuration to your settings.json
file. You'll need to modify it to handle the API key securely.
{
"mcp.servers": {
"functions-mcp": {
"type": "serverSideEvents",
"url": "YOUR_AZURE_FUNCTION_URL",
"header": {
"x-functions-key": "${input:functions-mcp-key}"
}
}
},
"mcp.inputs": [
{
"id": "functions-mcp-key",
"type": "password",
"description": "API key for the Azure Function"
}
]
}
When you start the server in VS Code, it will prompt for the API key. After entering the key, the server will start, and the available tools (over 4+ in this case) will be listed.
Now, you can interact with your custom tools through the GitHub Copilot chat.
Example 1: Hello World
- Prompt:
@workspace hello, use your MCP tools
- Action: Copilot finds and runs the
hello
tool, outputting the custom greeting.
- Prompt:
Example 2: Saving and Getting a Snippet
- Prompt:
@workspace save the following snippet
- Action: Copilot recognizes the
save snippet
tool and prompts for the required parameters:name
andcontent
. - Input: Provide "code" as the name and
const hello = 'hello';
as the content. - Result: The snippet is successfully saved.
- Prompt:
@workspace get the snippet named code
- Action: Copilot runs the
get snippets
tool and returns the saved content:const hello = 'hello';
.
- Prompt:
This demonstrates how you can effectively create and integrate a remote MCP server using Azure Functions, extending the capabilities of your AI assistants to interact with your own systems and data.
Join the 10xdev Community
Subscribe and get 8+ free PDFs that contain detailed roadmaps with recommended learning periods for each programming language or field, along with links to free resources such as books, YouTube tutorials, and courses with certificates.