这是一个快速入门模板,可以轻松构建并部署一个自定义的远程 MCP 服务器到云端,使用 Azure 函数。您可以在本地机器上进行克隆/恢复/运行,并通过调试,使用 azd up 在几分钟内将其部署到云端。MCP 服务器通过设计使用密钥和 HTTPS 进行安全保护,并允许通过 EasyAuth 和/或 API 管理以及 VNET 进行网络隔离来提供更多 OAuth 选项。
观看视频概述
<a href="https://www.youtube.com/watch?v=XwnEtZxaokg"> <img src="./images/video-overview.png" alt="观看视频" width="500" /> </a>如果您正在寻找更多语言的示例,请查看 Node.js/TypeScript 和 Python 示例。
4.0.7030选择一种:您可以使用 Visual Studio 或 Visual Studio Code。两者都提供完整的调试支持,但设置步骤略有不同。
以下是使用 Azure Functions 的远程 MCP 服务器架构图:

此特定示例需要 Azure 存储模拟器,因为我们将从 Blob 存储中保存和获取片段。
启动 Azurite
docker run -p 10000:10000 -p 10001:10001 -p 10002:10002 \
mcr.microsoft.com/azure-storage/azurite
注意 如果您使用来自 VS Code 扩展的 Azurite,现在需要运行
Azurite: Start,否则您会看到错误。
选择您偏好的开发环境:
从 src 文件夹,运行以下命令以启动本地的函数主机:
cd src
func start
请注意,默认情况下这将使用 webhook 路由:/runtime/webhooks/mcp。稍后我们将在 Azure 中设置客户端/主机调用的密钥:/runtime/webhooks/mcp?code=<system_key>
一旦您的 Azure Functions MCP 服务器在本地运行(通过 Visual Studio Code 或 Visual Studio),您可以从各种 MCP 客户端工具连接到它:
添加 MCP 服务器 从命令面板添加 URL 到正在运行的函数应用的 MCP 终点:
http://localhost:7071/runtime/webhooks/mcp
注意:如果您是从 Visual Studio(而不是 VS Code)运行,请使用
http://localhost:7071/runtime/webhooks/mcp/sse。
列出 MCP 服务器 从命令面板开始服务器
在 Copilot 聊天代理模式下输入提示以触发工具,例如,选择一些代码并输入以下提示
说你好
将此片段保存为 snippet1
检索 snippet1 并应用于 NewFile.cs
当提示运行工具时,点击 继续 同意
当您完成时,在终端窗口中按 Ctrl+C 停止 func.exe 主机进程(或在您的 IDE 中停止调试)。
在 新的终端窗口 中,安装并运行 MCP Inspector
npx @modelcontextprotocol/inspector node build/index.js
CTRL 点击以从应用程序显示的 URL 加载 MCP Inspector Web 应用(例如 http://0.0.0.0:5173/#resources)
设置传输类型为 Streamable HTTP
设置 URL 为正在运行的函数应用的 MCP 终点并 连接:
http://0.0.0.0:7071/runtime/webhooks/mcp
注意:如果您是从 Visual Studio(而不是 VS Code)运行,请使用
http://localhost:7071/runtime/webhooks/mcp/sse。
列出工具。点击一个工具并 运行工具。
问题:尝试连接到 MCP 服务器时连接被拒绝
docker run -p 10000:10000 -p 10001:10001 -p 10002:10002 mcr.microsoft.com/azure-storage/azurite)问题:错误的 URL(0.0.0.0 与 localhost)
http://0.0.0.0:7071/runtime/webhooks/mcp/sse,对于 Visual Studio 使用 http://localhost:7071/runtime/webhooks/mcp/sse问题:Visual Studio F5 不起作用
FunctionsMcpTool 已设置为启动项目在本地测试片段保存功能之后,您可以验证片段是否正确存储在本地 Azurite 存储模拟器中。
如果您更喜欢使用命令行,也可以使用 Azure CLI 与存储模拟器验证 Blob:
# 列出 snippets 容器中的 Blob
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;"
# 下载特定 Blob 以查看其内容
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;"
此验证步骤确保您的 MCP 服务器正确地与本地存储模拟器交互,并且在部署到 Azure 之前 Blob 存储功能按预期工作。
运行此 azd 命令以配置函数应用,包括任何所需的 Azure 资源,并部署您的代码:
azd up
您可以选择在示例中使用 VNet。要在 azd up 之前这样做,请执行以下操作:
azd env set VNET_ENABLED true
此外,API 管理 可用于提高 MCP 服务器的安全性和策略,而 App Service 内置身份验证 可用于设置您最喜欢的 OAuth 提供商,包括 Entra。
您的客户端需要一个密钥才能调用新的托管 MCP 终点,该密钥的形式为 https://<funcappname>.azurewebsites.net/runtime/webhooks/mcp。托管函数默认需要一个系统密钥,可以从 门户 或 CLI (az functionapp keys list --resource-group <resource_group> --name <function_app_name>) 获取。获取名为 mcp_extension 的系统密钥。
对于 MCP Inspector,您可以在 URL 中包含密钥:
https://<funcappname>.azurewebsites.net/runtime/webhooks/mcp?code=<your-mcp-extension-system-key>
对于 GitHub Copilot 在 VS Code 中,您应将密钥设置为 mcp.json 中的 x-functions-key 头,并且您只需使用 https://<funcappname>.azurewebsites.net/runtime/webhooks/mcp 作为 URL。以下示例使用输入,并在您从 VS Code 启动服务器时提示您提供密钥。注意 mcp.json 已包含在此仓库中并将被 VS Code 捕获。点击服务器上的“开始”以提示输入值,包括 functionapp-name(在您的 /.azure/*/.env 文件中)和 functions-mcp-extension-system-key,这些可以从上面的 CLI 命令或函数应用的门户中的 API 密钥获取。
{
"inputs": [
{
"type": "promptString",
"id": "functions-mcp-extension-system-key",
"description": "Azure Functions MCP 扩展系统密钥",
"password": true
},
{
"type": "promptString",
"id": "functionapp-name",
"description": "Azure Functions 应用名称"
}
],
"servers": {
"remote-mcp-function": {
"type": "http",
"url": "https://${input:functionapp-name}.azurewebsites.net/runtime/webhooks/mcp",
"headers": {
"x-functions-key": "${input:functions-mcp-extension-system-key}"
}
},
"local-mcp-function": {
"type": "http",
"url": "http://0.0.0.0:7071/runtime/webhooks/mcp"
}
}
}
点击服务器上的“开始”以提示输入值,包括 functionapp-name(在您的 /.azure/*/.env 文件中)和 functions-mcp-extension-system-key,这些可以从上面的 CLI 命令或函数应用的门户中的 API 密钥获取。
您可以根据需要多次运行 azd up 命令以配置 Azure 资源并部署代码更新到您的函数应用。
[!NOTE] 已部署的代码文件始终会被最新的部署包覆盖。
当您完成与函数应用及相关资源的工作时,可以使用此命令从 Azure 删除函数应用及其相关资源,避免产生进一步的成本:
azd down
GetSnippet 和 SaveSnippet 终点的函数代码定义在 SnippetsTool.cs 中。应用于异步 Run 方法的 McpToolsTrigger 属性将代码函数暴露为 MCP 服务器。
这展示了几个 MCP 服务器示例的代码(获取字符串、获取对象、保存对象):
[Function(nameof(SayHello))]
public string SayHello(
[McpToolTrigger(HelloToolName, HelloToolDescription)] ToolInvocationContext context
)
{
logger.LogInformation("说你好");
return "你好,我是 MCP 工具!";
}
[Function(nameof(GetSnippet))]
public object GetSnippet(
[McpToolTrigger(GetSnippetToolName, GetSnippetToolDescription)] ToolInvocationContext context,
[BlobInput(BlobPath)] string snippetContent)
{
return snippetContent;
}
[Function(nameof(SaveSnippet))]
[BlobOutput(BlobPath)]
public string SaveSnippet(
[McpToolTrigger(SaveSnippetToolName, SaveSnippetToolDescription)] ToolInvocationContext context,
[McpToolProperty(SnippetNamePropertyName, PropertyType, SnippetNamePropertyDescription)] string name,
[McpToolProperty(SnippetPropertyName, PropertyType, SnippetPropertyDescription)] string snippet)
{
return snippet;
}