Recently under the experimental Azure Functions build Microsoft Developer Advocates have shown enabling Azure Functions as MCP Servers. I wondered if it was possible to use this to MCP enable a number of my PowerShell Identity Tools Modules. Yes, yes it is possible. This post details how to build your own PowerShell MCP Azure Function Server.
Initially I saw the Python MCP Azure Function example. I wrote a Python wrapper to then call MCP enabled PowerShell Modules. It worked expertly locally. Deploy to Azure and FAIL. Fail because the Python Azure runtime is only supported on Linux nodes. Linux nodes don’t have PowerShell. Some searching and I found the .NET MCP Azure Function example. Perfect, as it supports Windows and PowerShell is then available and even better under the Consumption Plan model.
This post demonstrates how to expose PowerShell modules through Azure Functions (.NET) as MCP tools and in my example I’m exposing my JWTDetails and X509Details PowerShell modules. However, the possibilities are endless and the approach is scalable. I have many ideas for empowering AI with my PowerShell tools.
So how does it actually work? Below are the components, the flow and a deployed example. Jump to the end for the Repo and deployment steps.
The Function App below shows the JwtDetails and X509Details mcpToolTrigger endpoints from the deployed Azure Function. The health endpoint serves as the “heartbeat” of the MCP server, providing service status information.
Under API Keys you will see the mcp_extension system key. This is effectively your key to using the Azure Function. This is an example prototype. As the MCP Server Protocol matures I’ll be replacing this with oAuth.
The quickest way to test your MCP prior to using an MCP Client is to use MCP Inspector.
Select SSE and provide the URL with the key https://<functionapp>.azurewebsites.net/runtime/webhooks/mcp/sse?code=<yourMCPKey> then Connect. You will then be able to list the tools exposed via the MCP Server and provide input and run a tool. In the example above I’ve provided a self-signed certificate in pem format for the X509Details PowerShell Module cmdlet which returns the self-signed cert details including time to expiry.
In your MCP Client (e.g. VSCode or Claude) you provide the Azure Function URL and the MCP System Key retrieved from the deployment shown above.
In VSCode using the AI Toolkit via preferences you can add a new MCP Server and provide the path and key URL https://<functionapp>.azurewebsites.net/runtime/webhooks/mcp/sse?code=<yourMCPKey>. The type is SSE.
In Claude in Settings Add a Custom Connector. Provide the Azure Function URL and System Key URL https://<functionapp>.azurewebsites.net/runtime/webhooks/mcp/sse?code=<yourMCPKey>
Below is an example of Claude using the PowerShell MCP X509Details PowerShell Module tool and the LLM narrative around the result.
The codeblock below shows the wrapper to expose the Get-JWTDetails cmdlet as an MCP Server Tool and execute it using PowerShell converting the response to JSON and returning the result. The X509Details tool in the repo has some post-processing to manage the conversion from a deeper nested PSObject to JSON before returning the response.
[Function(nameof(JwtDetails))]
public async Task JwtDetails(
[McpToolTrigger(JwtDetailsToolName, JwtDetailsToolDescription)]
ToolInvocationContext context,
[McpToolProperty(TokenPropertyName, PropertyType, TokenPropertyDescription)]
string token)
{
try
{
_logger.LogInformation("Processing JWT Details request");
if (string.IsNullOrWhiteSpace(token))
{
return JsonSerializer.Serialize(new { error = "Token parameter is required" });
}
// Execute PowerShell command
var psCommand = $"Import-Module JWTDetails; Get-JWTDetails -token '{token}' | ConvertTo-Json -Depth 10";
var result = await _powerShellExecutor.ExecuteAsync(psCommand);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "JWT Details error");
return JsonSerializer.Serialize(new { error = $"Processing error: {ex.Message}" });
}
}
I built the solution locally in VSCode and validated everything was working locally and then used azd to deploy to Azure. Just as the examples had done. I did try using VSCode to publish to Azure Functions, but I just couldn’t get the project to publish. Sometime spent learning Bicep and azd had me successfully deploying and updating my MCP Azure Functions.
The simplified steps are:
# Azure Login
azd auth login
# List all subscriptions you have access to
az account list --output table
# Set the subscription using Azure CLI
az account set --subscription "Your-Subscription-Name-or-ID"
# Initialise the environment
azd init --environment <name for your environment>
# Deploy - it will use the configured subscription
azd deploy
Azure Developer CLI (azd) is a developer-centric command-line interface that simplifies the entire Azure application lifecycle from local development to cloud deployment. It provides:
To get started and up and running for yourself, start here.
Here is my repo with the full implementation. What will you MCP enable from your PowerShell library?
Today, I’m super excited to finally announce the Beta release of EntraPulse Lite – a…
I'm excited to share some significant authentication enhancements I've contributed to the Lokka MCP Server…
Last month I had the pleasure of speaking at the Sydney event for Global Azure.…
Model Context Protocol (MCP) is a powerful framework that extends AI clients like Claude and…
I've just completed participating in the Azure AI Developer Hackathon that was looking to provide…
Updated: July 2025 v1.0.2 Fixes issue setting D365SalesGlobals enabling session management for D365 Sales API…
This website uses cookies.