此示例展示了如何使用App Service身份验证和授权进行模型上下文协议(MCP)服务器授权。MCP服务器使用Azure Functions MCP扩展和TypeScript/Node.js实现。该示例还展示了如何代表已登录用户调用Microsoft Graph。
示例使用一个TypeScript项目。有两种方式开始:
您可以在本地运行它,也可以使用Azure开发者CLI(azd)快速将其部署到Azure。
您还需要一个Entra客户端ID,可以由您的MCP客户端使用。对于基本测试,您可以使用Visual Studio Code,它有一个已知的客户端ID,将在设置说明中解释。
azd部署到Azure)克隆此仓库。
登录Azure并初始化azd:
az login
azd auth login
创建一个新的azd项目环境,指定位置(建议使用westus2),您要使用的订阅ID以及环境名称:
azd env new <environment-name> --location westus2 --subscription <subscription-id>
此示例使用Visual Studio Code作为主要客户端。配置它为允许的客户端应用:
azd env set PRE_AUTHORIZED_CLIENT_IDS aebc6443-996d-45c2-90f0-388ff96faa56
如果您有其他MCP客户端将调用您的服务器,请提供所有客户端ID作为逗号分隔的列表:
azd env set PRE_AUTHORIZED_CLIENT_IDS <comma-separated-list-of-client-ids>
如果您的组织需要服务管理引用,请指定它。**如果您不是微软员工且不知道是否需要设置此引用,可以跳过这一步。**然而,如果由于缺少服务管理引用而导致配置失败,您可能需要重新访问这一步。使用微软租户的微软员工必须提供服务管理引用(您的服务树ID)。没有这个,您将无法创建Entra应用注册,配置也会失败。
azd env set SERVICE_MANAGEMENT_REFERENCE <service-management-reference>
如果您不确定应该设置什么,请咨询您的组织租户管理员。
(可选)如果您正在部署到主权云,请设置用于该云的令牌交换受众。
对于Entra ID美国政府版:
azd env set TOKEN_EXCHANGE_AUDIENCE api://AzureADTokenExchangeUSGov
对于由中国21Vianet运营的Entra ID中国版:
azd env set TOKEN_EXCHANGE_AUDIENCE api://AzureADTokenExchangeChina
创建Azure资源并部署应用程序:
azd up
确保所有资源都显示为“成功”状态后再继续。
同意应用程序,以便您的MCP客户端能够成功登录。为了测试,您只需通过浏览器登录应用程序来为自己授权。有关生产场景下的授权编写,请参阅授权编写。
导航到您部署的功能应用的/.auth/login/aad端点。例如,如果您的功能应用位于https://my-mcp-function-app.azurewebsites.net,则导航到https://my-mcp-function-app.azurewebsites.net/.auth/login/aad。
您的功能应用基础URL应在azd up命令的输出中显示。如果您错过了部署输出中的URL,可以通过以下命令检索:
azd env get-value SERVICE_MCP_DEFAULT_HOSTNAME
或者,在Azure门户中找到您的功能应用资源。
您应被重定向到登录提示。使用您将用于测试的MCP客户端的账户登录。
登录后,您将被提示同意应用程序。查看请求的权限并点击“接受”以授予同意。
您应被重定向回一个页面,该页面位于功能应用URL上,显示“您已成功登录”。此时您可以关闭页面。
获取您的功能应用的MCP扩展系统密钥,以便连接MCP客户端。您的客户端除了需要与Entra ID进行服务器授权外,还需要此密钥来调用您的MCP服务器。
您可以使用Azure CLI获取名为mcp_extension的系统密钥。首先,从您的azd部署中获取资源组和功能应用名称:
# 获取资源组名称
azd env get-value AZURE_RESOURCE_GROUP_NAME
# 获取功能应用名称
azd env get-value SERVICE_MCP_NAME
然后使用这些值来检索系统密钥:
az functionapp keys list --resource-group <resource_group> --name <function_app_name> --query "systemKeys.mcp_extension" -o tsv
或者,您可以从Azure门户中检索它:
mcp_extension系统密钥的值根据下面的测试您的MCP服务器部分中的说明测试您的MCP服务器。您需要功能应用URL和上一步中的mcp_extension系统密钥。
[!注意] 当本地运行时,MCP服务器将使用您的开发者凭据(来自Azure CLI或Visual Studio Code)对外部调用Microsoft Graph,而不是授权用户的标识。
克隆此仓库。
(可选)更新src/mcp-server文件夹中的local.settings.json文件,以包含您的Microsoft Entra租户ID。这有助于应用程序正确访问您的开发者身份,即使您可以登录多个租户。
使用Azure CLI获取租户ID:
az account show --query tenantId -o tsv
更新local.settings.json以包含租户ID:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node",
"AZURE_TENANT_ID": "<your-tenant-id>"
}
}
启动Azurite。如果您使用CLI启动它,例如使用azurite或docker run命令,请在单独的后台终端中执行。
将主终端移动到src/mcp-server文件夹。
安装依赖项:
npm install
启动项目:
npm start
根据下面的测试您的MCP服务器部分中的说明测试您的MCP服务器。
完成上述任一“快速入门”选项后,您可以连接到MCP客户端来测试结果MCP服务器。
以下说明是针对使用Visual Studio Code中的GitHub Copilot进行测试的,它支持MCP协议和Entra ID身份验证。此设置还提供了日志,使客户端和服务器之间的交互易于观察,从而了解服务器授权过程。
在VS Code中创建一个新的工作区,并安装MCP扩展。
创建或更新您的MCP配置在VS Code中。将以下内容添加到您的mcp.json文件中(或创建一个):
{
"inputs": [
{
"type": "promptString",
"id": "functions-mcp-extension-system-key",
"description": "Azure Functions MCP Extension System Key",
"password": true
},
{
"type": "promptString",
"id": "functionapp-host",
"description": "The host domain of the function app."
}
],
"servers": {
"remote-mcp-function": {
"type": "http",
"url": "https://${input:functionapp-host}/runtime/webhooks/mcp",
"headers": {
"x-functions-key": "${input:functions-mcp-extension-system-key}"
}
},
"local-mcp-function": {
"type": "http",
"url": "http://localhost:7071/runtime/webhooks/mcp"
}
}
}
这创建了两个服务器配置,分别对应上述两种“快速入门”选项。在后续步骤中,请选择与您设置MCP服务器的方式相匹配的服务器,无论是本地还是远程。
(可选)显示输出日志:
Ctrl+Shift+PCmd+Shift+Premote-mcp-function或local-mcp-function)启动MCP服务器:
Ctrl+Shift+PCmd+Shif-Premote-mcp-function或local-mcp-function)remote-mcp-function,您将被提示:
mcp_extension系统密钥如果您连接到受App Service身份验证和授权保护的应用程序,VS Code将提示您允许GitHub Copilot访问您的Microsoft帐户。按照提示登录。
如果您配置了调试输出日志,您应该能看到MCP客户端和服务器在登录过程中是如何交互的。有关更多细节,请参阅服务器授权协议。
打开GitHub Copilot聊天面板(Ctrl+Alt+I)并输入提示以使用工具。确保调用工具的最简单方法是发送消息#HelloTool。
GitHub Copilot应提示您允许其调用工具。确认它将调用正确的服务器,然后允许其继续。
您应在聊天面板中看到来自工具的响应。它应该以您的名字问候您,并显示您的电子邮件。这些信息来自MCP服务器调用的Microsoft Graph。
MCP服务器的代码位于src/mcp-server项目文件夹中。这是一个使用TypeScript和Node.js的Azure Functions项目,使用Azure Functions的MCP扩展和自定义处理器。MCP处理器定义在mcp-handler/function.json中,并在index.ts中实现了一个工具。此函数的目标是调用Microsoft Graph并返回简单的问候语。当托管在Azure中时,它会代表已登录用户调用Graph。当本地运行时,它将使用您的开发者凭据。
为了满足这些需求,处理器使用@azure/identity包来获取正确的用户令牌。index.ts文件根据上下文配置适当的TokenCredential实例。在本地上下文中,这是一个简单的ChainedTokenCredential。然而,当托管在Azure中并使用App Service身份验证和授权时,处理器使用MCP工具触发器的ToolInvocationContext来访问底层HTTP传输的标头。它使用这些标头来构建自定义令牌凭证实现。此实现使用OnBehalfOfCredential,作为联合身份凭证认证为应用程序注册,该注册是在配置期间设置的托管身份。
使用带有@azure/identity包的自定义处理器的方法保持了工具实现的简洁性和核心目的,而不引入不必要的复杂性。这也允许在需要的情况下跨多个工具使用相同的设置。
在上述示例步骤中,您通过浏览器登录应用程序来同意它。这允许应用程序请求对Microsoft Graph的委托权限。处理授权主要有两种方式:
此示例中的用户授权是一个单独的登录,因为示例使用Visual Studio Code作为客户端。尽管Visual Studio Code预先授权给我们的应用程序,但这仅创建了用户调用MCP服务器的授权。它不会创建MCP服务器代表用户调用Microsoft Graph的授权。当我们直接登录应用程序时,我们会在组合授权体验中请求Microsoft Graph权限。
主要区别在于,由于Visual Studio Code使用单一登录流,因此它只会请求MCP服务器的令牌。它不会提供机会让用户交互式地同意MCP服务器所需的任何权限。如果您构建了一个使用某种交互式登录的客户端,它可以完全由该客户端处理。在这种情况下,不需要单独的浏览器登录。
有关Entra ID如何处理授权的更多信息,请参阅Microsoft身份平台中的权限和授权概述。
在VS Code的调试输出中,您将看到一系列请求和响应,这是MCP客户端和服务器交互的结果。当使用MCP服务器授权时,您应该看到以下事件序列:
有关完整协议的更多信息,请参阅MCP规范。