Remote MCP Servers using Azure Functions : Getting Started

Remote MCP Servers using Azure Functions : Getting Started

Project Overview

This project implements a Model Context Protocol (MCP) server using Azure Functions with .NET 10. The application exposes multiple tools through MCP that can be invoked by MCP-compatible clients for various operations including health checks, product information retrieval, and user profile management.

Table of Contents


Architecture

The application follows a serverless architecture pattern using Azure Functions with the isolated worker model. It leverages the Model Context Protocol to expose tools that can be consumed by AI assistants and other MCP clients.

Key Components:

  • Azure Functions Runtime: v4
  • Worker Model: Isolated (.NET 10)
  • Protocol: Model Context Protocol (MCP)
  • Monitoring: Application Insights integration
  • Logging: Console logging with configurable log levels

Technology Stack

  • .NET: 10.0
  • Azure Functions: v4
  • Model Context Protocol: v0.5.0-preview.1
  • Application Insights: v2.23.0
  • Runtime: dotnet-isolated worker

Project Structure

src/
 FunctionApp/
     Functions/
        PingFunction.cs
        ProductInfoFunction.cs
        UserProfileFunction.cs
     Program.cs
     FunctionApp.csproj
     host.json
     local.settings.json

Directory Layout

Path Description
Functions/ Contains all MCP tool function implementations
Program.cs Application entry point and service configuration
FunctionApp.csproj Project file with dependencies and build configuration
host.json Azure Functions host configuration
local.settings.json Local development settings

MCP Tools

The application exposes three MCP tools:

1. PingFunction

Purpose: Health check endpoint to verify the MCP server is running.

Trigger: McpToolTrigger

  • Name: PingFunction
  • Description: “Check if the MCP server is running.”

Parameters:

  • message (string, optional): Optional message to echo back

Response:

  • Returns “? MCP server is alive.” if no message provided
  • Echoes back the message if provided: “? MCP server received: {message}”

Example Usage:

{
  "tool": "PingFunction",
  "parameters": {
    "message": "Hello"
  }
}

2. ProductInfoFunction

Purpose: Retrieve product information by product code.

Trigger: McpToolTrigger

  • Name: ProductInfoFunction
  • Description: “Get product information by product code.”

Parameters:

  • productCode (string, required): The product code

Supported Product Codes:

  • P100: Laptop – $1200 – Available
  • P200: Monitor – $300 – Out of stock
  • P300: Keyboard – $80 – Available

Response:
Returns formatted product information including:

  • Product name
  • Price
  • Stock availability

Example Usage:

{
  "tool": "ProductInfoFunction",
  "parameters": {
    "productCode": "P100"
  }
}

Response:

Product: Laptop
Price: $1200
Stock: Available

3. UserProfileFunction

Purpose: Retrieve basic user profile information.

Trigger: McpToolTrigger

  • Name: UserProfileFunction
  • Description: “Get basic user profile information.”

Parameters:

  • userId (string, required): The user identifier

Supported User IDs:

  • alice: Administrator – Active
  • bob: Developer – Active
  • charlie: Viewer – Disabled

Response:
Returns formatted user profile including:

  • Name
  • Role
  • Status

Example Usage:

{
  "tool": "UserProfileFunction",
  "parameters": {
    "userId": "alice"
  }
}

Response:

Name: Alice
Role: Administrator
Status: Active

Getting Started

Prerequisites

  • .NET 10 SDK
  • Azure Functions Core Tools (v4)
  • Azure Storage Emulator or Azure Storage Account
  • Visual Studio 2022 (or later) or VS Code with Azure Functions extension
  • VS Code MCP extension (for testing)

Install Azure Functions Core Tools

winget install Microsoft.Azure.FunctionsCoreTools

Local Development Setup

  1. Clone the repository:

    git clone https://github.com/azurecorner/remote-MCP-servers-using-azure-functions
    cd remote-MCP-servers-using-azure-functions/src
    
  2. Restore dependencies:

    dotnet restore
    
  3. Build the project:

    dotnet build
    
  4. Configure local settings:
    Ensure local.settings.json is properly configured (see Configuration)

  5. Run the application:

    func start
    

    or

    dotnet run
    

    Expected Output:

    Azure Functions Core Tools
    Core Tools Version:       4.6.0+ab90faafcab539d63cd3d0ce5faf1bca4395fccc (64-bit)
    Function Runtime Version: 4.1045.200.25556
    
    MCP server endpoint: http://localhost:7071/runtime/webhooks/mcp
    MCP server legacy SSE endpoint: http://localhost:7071/runtime/webhooks/mcp/sse
    
    Worker process started and initialized.
    
    Functions:
         PingFunction: mcpToolTrigger
         ProductInfoFunction: mcpToolTrigger
         UserProfileFunction: mcpToolTrigger
    
    Host lock lease acquired by instance ID '000000000000000000000000F243C912'.
    

Configuration

local.settings.json

Configuration for local development:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
  }
}

Configuration Keys:

  • AzureWebJobsStorage: Storage connection string (use local emulator for development)
  • FUNCTIONS_WORKER_RUNTIME: Worker runtime type (dotnet-isolated)

host.json

Azure Functions host configuration:

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      },
      "enableLiveMetricsFilters": true
    }
  }
}

Features:

  • Application Insights integration
  • Telemetry sampling enabled
  • Live metrics support
  • Request logging excluded from sampling

Testing with VS Code

Starting the MCP Server

  1. Using Command Palette:

    • Press Ctrl + Shift + P in VS Code
    • Type and select: “Start MCP Server”
  2. Using Terminal:

    dotnet run
    

Configuring MCP Client

Add the following configuration to your MCP client settings:

{
  "servers": {
    "local-mcp-server": {
      "url": "http://localhost:7071/runtime/webhooks/mcp",
      "type": "http"
    }
  },
  "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"
    }
  ]
}

Verifying Connection

When the server starts successfully, you should see the following in the logs:

[info] Starting server local-mcp-server
[info] Connection state: Starting
[info] Starting server from LocalProcess extension host
[info] Connection state: Running
[info] Discovered 3 tools

Testing the MCP Tools

Once connected, you can test each tool through your MCP client:

1. Test PingFunction

{
  "tool": "PingFunction",
  "parameters": {
    "message": "Hello from VS Code"
  }
}

Expected Response: ? MCP server received: Hello from VS Code

2. Test ProductInfoFunction

{
  "tool": "ProductInfoFunction",
  "parameters": {
    "productCode": "P100"
  }
}

Expected Response:

Product: Laptop
Price: $1200
Stock: Available

3. Test UserProfileFunction

{
  "tool": "UserProfileFunction",
  "parameters": {
    "userId": "alice"
  }
}

Expected Response:

Name: Alice
Role: Administrator
Status: Active

Connection States

Monitor the connection state in the VS Code output:

State Description
Starting Server is initializing
Running Server is active and ready to accept requests
Stopped Server has been stopped
Error An error occurred during connection

Development

Adding New MCP Tools

  1. Create a new class in the Functions/ directory
  2. Implement the function with [Function] attribute
  3. Add [McpToolTrigger] to define the tool
  4. Use [McpToolProperty] for parameters
  5. Return appropriate response types

Template:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.Mcp;
using Microsoft.Extensions.Logging;

namespace FunctionApp.Functions;

public class YourNewFunction
{
    private readonly ILogger<YourNewFunction> _logger;

    public YourNewFunction(ILogger<YourNewFunction> logger)
    {
        _logger = logger;
    }

    [Function(nameof(YourNewFunction))]
    public async Task<string> Run(
        [McpToolTrigger(nameof(YourNewFunction), "Description of your tool")] ToolInvocationContext context,
        [McpToolProperty("paramName", "Parameter description")] string paramName)
    {
        _logger.LogInformation($"YourNewFunction invoked with: {paramName}");
        
        // Your implementation here
        
        await Task.CompletedTask;
        return "Your response";
    }
}

Logging

The application uses structured logging through ILogger<T>:

_logger.LogInformation("Message with {Parameter}", paramValue);
_logger.LogWarning("Warning message");
_logger.LogError(exception, "Error message");

Console logging is configured with trace-level output to standard error.


Deployment

Deployment instructions to Azure will be added later.


Dependencies

NuGet Packages

Package Version Purpose
Microsoft.Azure.Functions.Worker 2.51.0 Azure Functions isolated worker runtime
Microsoft.Azure.Functions.Worker.Sdk 2.0.7 SDK for building Azure Functions
Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore 2.1.0 ASP.NET Core integration for HTTP triggers
Microsoft.Azure.Functions.Worker.Extensions.Mcp 1.1.0 Model Context Protocol support
ModelContextProtocol.AspNetCore 0.5.0-preview.1 ASP.NET Core MCP implementation
Microsoft.ApplicationInsights.WorkerService 2.23.0 Application Insights telemetry
Microsoft.Azure.Functions.Worker.ApplicationInsights 2.50.0 Application Insights integration for Functions

Framework References

  • Microsoft.AspNetCore.App: ASP.NET Core shared framework

Features

Implemented

  • MCP server implementation with Azure Functions
  • Three sample MCP tools (Ping, ProductInfo, UserProfile)
  • Application Insights telemetry
  • Structured logging
  • Isolated worker model for better performance
  • Health check endpoint
  • VS Code integration for testing

Potential Enhancements

  • Database integration for dynamic data
  • Authentication and authorization
  • Rate limiting
  • Caching layer
  • Additional MCP tools
  • Integration tests
  • CI/CD pipeline
  • API documentation
  • Error handling middleware
  • Retry policies

Troubleshooting

Common Issues

  1. Storage Emulator Not Running:

    • Start Azure Storage Emulator or update AzureWebJobsStorage in local.settings.json
  2. Function Not Triggering:

    • Verify MCP client configuration
    • Check function logs for errors
    • Ensure all required parameters are provided
  3. Build Errors:

    • Clean and rebuild: dotnet clean && dotnet build
    • Restore packages: dotnet restore
    • Verify .NET 10 SDK is installed
  4. MCP Server Connection Issues:

    • Ensure the server is running on http://localhost:7071
    • Verify the MCP endpoint URL in client configuration
    • Check for port conflicts with other applications
    • Review the VS Code output logs for connection errors
  5. Tools Not Discovered:

    • Restart the MCP server
    • Verify the function bindings are correct
    • Check that all [McpToolTrigger] attributes are properly configured

Additional Resources


License

Please refer to the repository’s LICENSE file for licensing information.


Contributing

Contributions are welcome! Please follow standard pull request procedures and ensure all tests pass before submitting.


Source Code

github repository: https://github.com/azurecorner/remote-MCP-servers-using-azure-functions

Gora LEYE

I'm a microsoft most valuable professional (MVP) .NET Architect and Technical Expert skills located in Paris (FRANCE). The purpose of this blog is mainly to post general .NET tips and tricks, www.masterconduite.com Gora LEYE

Support us

BMC logoBuy me a coffee