FunctionsMcpTool Sample

June 1, 2026 · View on GitHub

A sample MCP server built with Azure Functions (Java) that demonstrates various MCP tools.

What It Does

This sample exposes three MCP tools:

ToolDescription
HelloWorldSays hello and logs the messages you provide.
SaveSnippetsSaves a text snippet to Azure Blob Storage.
GetSnippetsRetrieves a previously saved snippet by name.

Prerequisites

Note

This sample uses the Preview extension bundle (Microsoft.Azure.Functions.ExtensionBundle.Preview) because MCP prompt bindings (mcpPromptTrigger, mcpPromptArgument) are not yet available in the standard bundle. See host.json for the configuration.

Getting Started

1. Start the Storage Emulator

The snippet tools persist data in Azure Blob Storage. For local development, start Azurite:

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

Or use the Azurite VS Code extension and run Azurite: Start.

2. Build and Run

cd samples/FunctionsMcpTool
mvn clean package
mvn azure-functions:run

The MCP endpoint will be available at http://localhost:7071/runtime/webhooks/mcp.

3. Connect from VS Code

Open .vscode/mcp.json at the repo root. Find the server called local-mcp-function and click Start above the name.

4. Try the Tools

In Copilot chat (agent mode), try prompts like:

Say Hello
Save this snippet as snippet1
Retrieve snippet1 and apply to MyFile.java

Deploy to Azure

1. Sign in and create an environment

azd auth login

# This also becomes the resource group name
azd env new <environment-name>

2. Configure Entra authentication

Pre-authorize VS Code to request access tokens from Microsoft Entra:

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

Optional: Enable VNet isolation:

azd env set VNET_ENABLED true

3. Deploy

azd up

4. Connect to the remote MCP server

After deployment, open .vscode/mcp.json and click Start above remote-mcp-function. Enter the functionapp-name from your azd output (or /.azure/*/.env). You'll be prompted to authenticate with Microsoft — click Allow and sign in with your Azure subscription email.

Tip

A successful connection shows the number of tools the server has. Click More... -> Show Output for details on the VS Code ↔ server interactions.

Redeploy and clean up

Redeploy: Run azd up as many times as needed to deploy code updates.

Clean up: Delete all Azure resources when done:

azd down

Source Code

FileDescription
HelloWorld.javaSimple tool that logs messages and says hello.
Snippets.javaSave and retrieve snippets using @BlobOutput / @BlobInput bindings.
McpToolInvocationContext.javaPOJO for the MCP tool invocation context.

Key Concepts

MCP Tool Trigger — The @McpToolTrigger annotation exposes a Java function as an MCP tool:

@FunctionName("SaveSnippets")
@StorageAccount("AzureWebJobsStorage")
public String saveSnippet(
        @McpToolTrigger(
                name = "saveSnippets",
                description = "Saves a text snippet to your snippets collection.")
        String mcpToolInvocationContext,
        @McpToolProperty(name = "snippetName", propertyType = "string",
                description = "The name of the snippet.", isRequired = true)
        String snippetName,
        @McpToolProperty(name = "snippet", propertyType = "string",
                description = "The content of the snippet.", isRequired = true)
        String snippet,
        @BlobOutput(name = "outputBlob", path = BLOB_PATH)
        OutputBinding<String> outputBlob,
        final ExecutionContext functionExecutionContext) {
    outputBlob.setValue(snippet);
    return "Successfully saved snippet '" + snippetName + "'";
}

MCP Tool Properties — Use @McpToolProperty to declare input parameters that the MCP client passes to your tool.

Azure Bindings — Standard Azure Functions bindings (@BlobInput, @BlobOutput, @StorageAccount) work seamlessly with MCP triggers.

Troubleshooting

ProblemSolution
Connection refused locallyEnsure Azurite is running
API version not supported by AzuritePull the latest image: docker pull mcr.microsoft.com/azure-storage/azurite
mvn clean package failsEnsure JDK 17+ is on your PATH (java -version)
azd up provision succeeded but deploy immediately failed: unable to find a resource tagged with 'azd-service-name: mcp'The tag was provisioned but not propagated yet when azd deploy looked it up — run azd deploy again
azd deploy fails with Kudu restart error: deployment was partially successful: [KuduSpecializer] Kudu has been restarted after package deployedTransient error — run azd deploy again

Image tools cause "Could not process image" errors in VS Code

When using tools that return image content (renderImage, getMultiContent), you may see:

Request Failed: 400 {"message":"Could not process image"}

What's happening: The tools are returning content correctly — the function logic is working as expected. The image is returned and displayed successfully on the first response. However, on your next message, VS Code sends the full conversation history (including the image) back to the language model. The model endpoint may reject the image data in the history, causing the 400 error. This is a chat rendering/infrastructure issue, not a problem with the function app or MCP tool implementation.