你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

为模型上下文协议 (MCP) 工具设置身份验证

大多数模型上下文协议 (MCP) 服务器都需要身份验证才能访问服务器及其基础服务。 适当的身份验证可确保代理可以安全地连接到 MCP 服务器、调用其工具和访问受保护的资源,同时保持适当的访问控制。

在本文中,你将会:

  • 根据安全要求选择身份验证方法
  • 配置基于密钥、Microsoft Entra或 OAuth 身份验证
  • 设置并验证 MCP 服务器连接

注意

如果还没有 MCP 服务器发布者的帐户,请通过发布者的网站创建一个帐户。

先决条件

在开始之前,需要:

  • 访问 Foundry 门户和项目。 如果没有项目,请参阅 Foundry 中创建项目
  • 创建项目连接和配置代理的权限。 有关详细信息,请参阅 Foundry 门户中的基于角色的访问控制
  • 要连接到的远程 MCP 服务器终结点 URL。
  • 所选身份验证方法的凭据:
    • 基于密钥的身份验证:API 密钥、个人访问令牌(PAT)或其他令牌。
    • Microsoft Entra 身份验证:基础服务上代理标识或项目托管标识的角色分配。
    • OAuth 标识传递:托管 OAuth 配置或 OAuth 应用注册(自定义 OAuth)。

选择身份验证方法

一般情况下,存在两种身份验证方案:

  • 共享身份验证:代理的每个用户使用相同的标识向 MCP 服务器进行身份验证。 用户上下文不会持久保存。
  • 单个身份验证:每个用户使用自己的帐户进行身份验证,以便其用户上下文保持不变。

使用以下指南选择方法:

您的目标 建议的方法
为所有用户使用一个共享标识 基于密钥的身份验证或Microsoft Entra身份验证
保留每个用户的标识和权限 OAuth 身份传递
当基础服务支持Microsoft Entra时,避免管理机密 Microsoft Entra身份验证
连接到不需要身份验证的 MCP 服务器 未经身份验证的访问

提示

怀疑时,如果 MCP 服务器支持身份验证,请从Microsoft Entra身份验证开始。 Microsoft Entra身份验证无需管理机密并提供内置令牌轮换。

对于虚拟网络中的 private MCP 服务器,Microsoft Entra身份验证自然合适,因为代理和 MCP 服务器都位于同一专用网络上。

支持的身份验证方法

方法 描述 用户上下文仍然存在
基于密钥 提供 API 密钥或访问令牌,以便通过 MCP 服务器进行身份验证。
Microsoft Entra - 代理标识 使用代理标识向 MCP 服务器进行身份验证。 在基础服务上分配所需的角色。
Microsoft Entra - 项目托管标识 使用项目托管标识向 MCP 服务器进行身份验证。 在基础服务上分配所需的角色。
OAuth 身份传递 提示与代理交互的用户登录并授权访问 MCP 服务器。 是的
未经身份验证的访问 仅当 MCP 服务器不需要身份验证时,才使用此方法。

基于密钥的身份验证

当 MCP 服务器需要 API 密钥、个人访问令牌或类似凭据时,请使用基于密钥的身份验证,并且无需保留单个用户上下文。

注意

有权访问项目的人员可以访问存储在项目连接的 API 密钥。 仅将共享机密存储在项目连接中。 对于用户特定的访问,请使用 OAuth 身份透传。

将 API 密钥、个人访问令牌(PAT)或其他凭据传递给支持基于密钥的身份验证的 MCP 服务器。 为了提高安全性,请将共享凭据存储在项目连接中,而不是在运行时传递凭据。

将 MCP 服务器连接到 Foundry 门户中的代理时,Foundry 会为你创建项目连接。 提供凭据名称和凭据值。 例如,如果要连接到 GitHub MCP 服务器,则可能提供:

  • 凭据名称: Authorization
  • 凭据值: Bearer <your-personal-access-token>

当代理调用 MCP 服务器时,代理服务将从项目连接中检索凭据,并将其传递给 MCP 服务器。

为确保安全:

  • 尽可能使用最低特权凭据。
  • 定期轮换令牌。
  • 限制对包含共享机密的项目的访问。

Microsoft Entra身份验证

当 MCP 服务器(及其基础服务)支持Microsoft Entra令牌时,请使用Microsoft Entra身份验证。 此方法无需管理机密并提供自动令牌轮换。

使用代理身份验证

希望将身份验证范围限定为特定代理时使用代理标识。 如果有多个代理需要不同级别的访问同一 MCP 服务器,则此方法是理想的方法。

使用代理标识向支持代理标识身份验证的 MCP 服务器进行身份验证。 如果使用代理服务创建代理,则会自动向其分配代理标识。

发布之前,Foundry 项目中的所有代理共享相同的代理标识。 发布代理后,代理将获取唯一的代理标识。

确保代理标识在为 MCP 服务器提供支持的基础服务上具有所需的角色分配。

当代理调用 MCP 服务器时,代理服务使用可用的代理标识来请求授权令牌并将其传递给 MCP 服务器。

使用项目托管身份认证

如果希望项目中的所有代理共享相同的访问级别,或者当 MCP 服务器需要托管标识而不是代理标识时,请使用项目托管标识。

使用 Foundry 项目的托管标识通过支持托管标识身份验证的 MCP 服务器进行身份验证。

确保项目托管标识在为 MCP 服务器提供支持的基础服务上具有所需的角色分配。

当代理调用 MCP 服务器时,代理服务使用项目的托管标识请求授权令牌并将其传递给 MCP 服务器。

OAuth 身份传递

注意

  • 要使用 OAuth 标识直通,与你的智能体交互的用户需要在项目上至少拥有 Foundry 智能体使用者角色。 优先使用此角色,以实现最小权限访问。 Foundry 用户角色也可以使用,但它是为构建代理的开发人员而设,而不是为普通用户而设。 用户的 Microsoft Entra 租户必须与 Foundry 项目的租户匹配。 不支持跨租户令牌交换。
  • 强烈建议在作用域中添加 offline_access ,以便在令牌过期后自动刷新令牌。

重要

Foundry RBAC 角色最近已更名。 Foundry 用户Foundry 所有者Foundry 帐户所有者Foundry 项目经理之前的名称分别为“Azure AI 用户”、“Azure AI 所有者”、“Azure AI 帐户所有者”和“Azure AI 项目经理”。 在重命名推出时,你仍可能会在某些位置看到以前的名称。重命名后,角色 ID 和核心权限保持不变。

OAuth 标识直通可用于对符合 OAuth 标准(包括 Microsoft Entra)的 Microsoft 和非 Microsoft MCP 服务器及相关服务进行身份验证。

使用 OAuth 标识传递来提示与智能体交互的用户登录到 MCP 服务器及其基础服务。 代理服务安全地存储用户的凭据,并仅在与 MCP 服务器通信的代理上下文中使用这些凭据。

使用 OAuth 标识直通时,代理服务会在特定用户首次需要授权访问时生成同意链接。 用户登录和同意后,代理可以使用该用户的凭据发现和调用 MCP 服务器上的工具。

代理服务支持两个 OAuth 选项:托管 OAuth自定义 OAuth

  • 通过受管理的 OAuth,Microsoft 或 MCP 服务器发布商负责管理 OAuth 应用。
  • 使用自定义 OAuth 时,可以自带 OAuth 应用注册。

重要

使用 Microsoft Entra 的托管 OAuth 时,智能体服务会限制将作用域限定为已知 Microsoft 受众的令牌发送到自定义或第三方 MCP 服务器。 如果尝试此操作,代理服务将返回错误:Cannot pass Microsoft token to untrusted MCP endpoint.

你的自定义 MCP 服务器必须注册为面向由你控制的受众,而不是已知的 Microsoft 受众。 不要将 MCP 服务器设计成依赖于将其身份验证令牌透传给下游 Microsoft 服务。 若要满足此要求,请将自定义 OAuth 与自己的Microsoft Entra应用注册配合使用。

注意

如果使用自定义 OAuth,请在配置后收到重定向 URL。 将重定向 URL 添加到 OAuth 应用,以便代理服务可以完成流程。

设置 自定义 OAuth 时,请提供以下信息:

  • 客户端 ID:必需
  • 客户端密码:可选(取决于 OAuth 应用)
  • 身份验证 URL:必需
  • 刷新 URL:必须(如果没有单独的刷新 URL,可以使用令牌 URL 作为替代)
  • 令牌 URL:必需
  • 范围:可选(包含 offline_access 以启用自动刷新令牌)。 指定多个范围时,请用 一个空格(而不是逗号)分隔它们, 这遵循 OAuth 2.0 规范

使用 OAuth 身份传递的流程

在 Foundry 项目中,OAuth 的范围限定为每个工具(连接)的名称。 系统会提示在 Foundry 项目中使用新工具(连接)的每个新用户提供同意。

  • 当用户首次尝试在 Foundry 项目中使用新工具时,响应输出将共享许可链接。response.output_item 可以在项目类型oauth_consent_requestconsent_link下找到同意链接。 将此同意链接展示给用户。

    "type":"response.output_item.done",
    "sequence_number":7,
    "output_index":1,
    "item":{
        "type":"oauth_consent_request",
        "id":"oauthreq_10b0f026610e2b76006981547b53d48190840179e52f39a0aa",
        "created_by":{},
        "consent_link":"https://logic-swedencentral-001.consent.azure-apihub.net/login?data=xxxx"
    }
    

    请参阅示例: 显示 Foundry 门户中的同意对话框的屏幕截图。

  • 在查看所需的访问权限后,系统会提示用户登录并授予许可。 成功授予许可后,用户会看到如下例所示的对话框: 在 Foundry 门户中授予 OAuth 同意后显示确认对话框的屏幕截图。

  • 用户关闭对话框后,使用以前的响应 ID 提交另一个响应。 选择编程语言。

安装Python包:

pip install "azure-ai-projects>=2.0.0" azure-identity

设置 project_endpointagent_name 设置为现有项目终结点并提示代理名称。 第一个响应会显示 OAuth 同意链接:

from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential

project_endpoint = "https://<resource>.services.ai.azure.com/api/projects/<project>"
agent_name = "<agent-name>"
user_input = "Use the MCP tool to complete my request."

# Create clients to call the Foundry project and Responses APIs.
project = AIProjectClient(
   endpoint=project_endpoint,
   credential=DefaultAzureCredential(),
)
openai = project.get_openai_client()

# Send a request that requires the user to authorize the MCP connection.
response = openai.responses.create(
   input=user_input,
   tool_choice="required",
   extra_body={
      "agent_reference": {"name": agent_name, "type": "agent_reference"}
   },
)

for item in response.output:
   if item.type == "oauth_consent_request":
      print(f"Open this URL to authorize access: {item.consent_link}")

用户完成同意后,请继续执行上一个响应并使用流式响应:

# Continue the response after the user completes OAuth consent.
stream = openai.responses.create(
   previous_response_id=response.id,
   input=user_input,
   tool_choice="required",
   stream=True,
   extra_body={
      "agent_reference": {"name": agent_name, "type": "agent_reference"}
   },
)

for event in stream:
   if event.type == "response.output_text.delta":
      print(event.delta, end="", flush=True)
print()

参考: AIProjectClient响应 API

创建.NET控制台应用程序并安装 GA 包:

dotnet new console --name McpOAuthClient
cd McpOAuthClient
dotnet add package Azure.AI.Projects --version 2.0.1
dotnet add package Azure.AI.Extensions.OpenAI --version 2.0.0
dotnet add package Azure.Identity

Program.cs 的内容替换为以下代码。 设置 projectEndpointagentName 设置为现有项目终结点并提示代理名称:

using Azure.AI.Extensions.OpenAI;
using Azure.AI.Projects;
using Azure.Identity;
using OpenAI.Responses;

#pragma warning disable OPENAI001

var projectEndpoint =
   "https://<resource>.services.ai.azure.com/api/projects/<project>";
var agentName = "<agent-name>";
var userInput = "Use the MCP tool to complete my request.";

// Create clients to call the Foundry project and Responses APIs.
AIProjectClient projectClient = new(
   endpoint: new Uri(projectEndpoint),
   tokenProvider: new DefaultAzureCredential());
ProjectResponsesClient responsesClient = projectClient.ProjectOpenAIClient
   .GetProjectResponsesClientForAgent(agentName);

// Send a request that requires the user to authorize the MCP connection.
CreateResponseOptions initialOptions = new()
{
   ToolChoice = ResponseToolChoice.CreateRequiredChoice(),
};
initialOptions.InputItems.Add(
   ResponseItem.CreateUserMessageItem(userInput));
ResponseResult response = await responsesClient.CreateResponseAsync(
   initialOptions);

foreach (ResponseItem item in response.OutputItems)
{
   if (item.AsAgentResponseItem() is
      OAuthConsentRequestResponseItem consentRequest)
   {
      Console.WriteLine(
         $"Open this URL to authorize access: {consentRequest.ConsentLink}");
   }
}

Console.WriteLine("Press Enter after you complete consent.");
Console.ReadLine();

// Continue the response after the user completes OAuth consent.
CreateResponseOptions continuationOptions = new()
{
   PreviousResponseId = response.Id,
   ToolChoice = ResponseToolChoice.CreateRequiredChoice(),
};
continuationOptions.InputItems.Add(
   ResponseItem.CreateUserMessageItem(userInput));

await foreach (StreamingResponseUpdate update in responsesClient
   .CreateResponseStreamingAsync(continuationOptions))
{
   if (update is StreamingResponseOutputTextDeltaUpdate textDelta)
   {
      Console.Write(textDelta.Delta);
   }
}
Console.WriteLine();

参考: AIProjectClientProjectResponsesClientOAuthConsentRequestResponseItem

用户登录并授予许可一次后,他们将来无需同意。

注意

如果用户拒绝同意,MCP 工具调用将失败并返回错误。 应用程序应正常处理此情况,并通知用户该工具需要授权才能正常运行。

自带 Microsoft Entra 应用注册

注意

代理 365 MCP 服务器仅适用于 Frontier 租户

要在 Microsoft 服务中使用标识传递,请自带 Microsoft Entra 应用注册。 通过自带Microsoft Entra应用注册,可以控制授予的权限。

以下步骤使用 Agent 365 MCP 服务器作为示例:

  1. 按照 应用注册指南创建Microsoft Entra应用并获取客户端 ID 和客户端密码。

  2. 向Microsoft Entra应用授予范围权限

    对于代理 365 MCP 服务器,请转到 “管理>API 权限 ”并搜索 代理 365 工具。 如果找不到它,请搜索 ea9ffc3e-8a23-4a7d-836d-234d7c7565c1。 分配所需的权限,并为租户授予管理员许可。

    下面是每个 MCP 服务器的权限:

    • Microsoft Outlook邮件 MCP 服务器(前端):McpServers.Mail.All
    • Microsoft Outlook 日历 MCP 服务器 (Frontier):McpServers.Calendar.All
    • Microsoft Teams MCP 服务器(边界):McpServers.Teams.All
    • Microsoft 365 用户配置文件 MCP 服务器 (Frontier):McpServers.Me.All
    • Microsoft SharePoint和OneDrive MCP 服务器(边界):McpServers.OneDriveSharepoint.All
    • Microsoft SharePoint 列表 MCP 服务器 (Frontier):McpServers.SharepointLists.All
    • Microsoft Word 日历 MCP 服务器(边界):McpServers.Word.All
    • 智能 智能 Microsoft 365 Copilot 副驾驶® 副驾驶®(搜索)MCP 服务器 (Frontier):McpServers.CopilotMCP.All
    • Microsoft 365 管理中心 MCP 服务器(前沿):McpServers.M365Admin.All
    • Microsoft Dataverse MCP 服务器(Frontier):McpServers.Dataverse.All
  3. 返回到 Foundry 门户 并配置 MCP 服务器。 连接工具,转到 “自定义”,然后选择 MCP。 提供名称和 MCP 服务器终结点,然后选择“OAuth 标识传递”

    • 客户端 ID 和客户端密码
    • 令牌 URL: https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token
    • 身份验证 URL: https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize
    • 刷新 URL: https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token
    • 范围:ea9ffc3e-8a23-4a7d-836d-234d7c7565c1/{permission above} offline_access(根据 OAuth 2.0 规范,以空格分隔)
  4. 完成配置后,会收到 重定向 URL。 将其添加到Microsoft Entra应用。

未经身份验证的访问

仅当 MCP 服务器不需要身份验证时,才使用未经身份验证的访问。 此方法适用于提供对其工具的开放访问权限的公共 MCP 服务器,或者适用于依赖于网络级别隔离而不是显式身份验证的虚拟网络中的专用 MCP 服务器。

重要

即使不需要身份验证,请确保在连接之前了解 MCP 服务器的服务条款和速率限制。

为 MCP 服务器设置身份验证

  1. 标识要连接到的远程 MCP 服务器。

  2. 创建或选择存储 MCP 服务器终结点、身份验证类型和任何所需凭据的项目连接。

    如果在 Foundry 门户中连接 MCP 服务器,门户会为你创建项目连接。

  3. 使用 mcp 工具,根据以下信息创建或更新代理:

    1. server_url:MCP 服务器的 URL。 例如, https://api.githubcopilot.com/mcp/.
    2. server_label:用于代理的此 MCP 服务器的唯一标识符。 例如, github.
    3. require_approval:(可选)确定是否需要审批。 支持的值包括:
      • always:开发人员需要为每个呼叫提供审批。 如果未提供值,则此值为默认值。
      • never:无需审批。
      • {"never":[<tool_name_1>, <tool_name_2>]}:提供不需要审批的工具列表。
      • {"always":[<tool_name_1>, <tool_name_2>]}:提供需要审批的工具列表。
    4. project_connection_id:存储 MCP 服务器终结点、身份验证选择和相关信息的连接名称。 如果在连接(而不是 server_url)中提供不同的终结点,则使用连接中的终结点。
  4. 运行代理。

  5. 如果模型尝试在 MCP 服务器中调用工具,但需要批准,或者用户需要登录 OAuth 标识直通,请查看响应输出:

    • 同意链接:oauth_consent_request
    • 审批请求: mcp_approval_request

    用户登录或批准呼叫后,请提交另一个响应以继续。

验证

配置身份验证后,验证连接是否正常工作:

  1. 通过发送导致代理使用 MCP 服务器工具之一的提示来触发 MCP 工具调用。
  2. 确认工具调用成功完成。 你应该在代理的响应中看到该工具的输出,且不会出现身份验证错误。
  3. 如果使用 OAuth 身份验证传递:
    • 确认新用户收到同意链接(oauth_consent_request 响应中)。
    • 用户同意后,确认后续工具调用成功,而无需再次提示同意。
    • 使用其他用户进行测试,以验证每用户同意流是否正常工作。

故障 排除

问题 原因 分辨率
你未在预期时收到 oauth_consent_request MCP 工具未针对 OAuth 标识传递进行配置,或者工具调用未执行 确认项目连接已配置为 OAuth 身份直通,确保您的提示会导致代理调用 MCP 工具。
同意完成,但工具调用仍然失败 基础服务中缺少访问权限 确认用户有权访问相关底层服务,并在项目中拥有 Foundry 用户 角色(或更高权限)。
基于密钥的身份验证失败 无效或过期的密钥或令牌,或者 MCP 服务器需要不同的标头名称或值格式 重新生成或轮换凭据并更新项目连接。 在 MCP 服务器文档中确认所需的标头名称和值格式。
Microsoft Entra身份验证失败 标识没有所需的角色分配 将所需的角色分配给基础服务上的代理标识或项目托管标识,然后重试。
工具调用意外被阻止 require_approval 被设置为 always (默认值),或者配置要求调用的工具获得批准 更新 require_approval 以符合审批要求。
尽管凭据有效,MCP 服务器仍返回“未授权” 凭据标头名称或格式与 MCP 服务器所需的名称或格式不匹配 查看 MCP 服务器的文档,了解确切的标头名称(例如,AuthorizationX-API-KeyApi-Key)和值格式(例如,Bearer <token>与仅值<token>)。
OAuth 令牌过期,工具调用在一段时间后失败。 “你的会话已过期。 请使用提供的 URL 重新进行身份验证。 刷新令牌无效或刷新 URL 不正确 验证刷新 URL 是否正确。 如果将令牌 URL 用作刷新 URL,请确认 OAuth 提供程序支持在该终结点刷新令牌。 如果吊销刷新令牌,用户可能需要再次同意。 请确保在创建 OAuth 身份验证连接时,将 offline_access 添加到 scope 中。
无法从代理访问专用 MCP 服务器 MCP 服务器不在专用 MCP 子网上,子网委派缺失,或者专用 DNS 解析失败 验证 MCP 服务器是否部署在具有 Microsoft.App/environments 委派的 MCP 子网上。 检查专用 DNS 区域配置。 使用 19-hybrid-private-resources-agent-setup 模板进行部署。

托管本地 MCP 服务器

如果你开发了自定义 MCP 服务器,或者想要使用在本地运行的开源 MCP 服务器,则需要将其托管在云中,然后再将其连接到代理服务。

代理服务运行时仅接受远程 MCP 服务器终结点。 如果要从本地 MCP 服务器添加工具,则需要在 Azure 容器应用Azure Functions 上自行托管该工具以获取远程 MCP 服务器终结点。

远程终结点可以是公共终结点,也可以是 VNet 中的专用终结点。 对于专用 MCP 服务器,请在委托给 Microsoft.App/environments 的专用 MCP 子网上部署仅限内部的入口的容器应用。 若要开始,请使用 19-hybrid-private-resources-agent-setup 模板。 有关网络隔离环境中的工具支持的详细信息,请参阅 具有网络隔离的代理工具

尝试在云中托管本地 MCP 服务器时,请考虑以下几点:

本地 MCP 服务器设置 在 Azure 容器应用 中托管 在 Azure Functions 中托管
运输 需要 HTTP POST/GET 终结点。 需要支持 HTTP 可流式传输(响应必须支持针对 SSE 样式流式传输的分块传输编码)。
代码更改 容器需要重建。 根目录中需要 Azure Functions 特定的配置文件。
认证 需要自定义身份验证实现。 使用 内置身份验证 或自定义代码。

默认情况下,Azure Functions 需要密钥,但你可以在host.json中禁用密钥要求。
语言堆栈 在 Linux 容器中运行的任何语言(Python、Node.js、.NET、TypeScript、Go)。 仅Python、Node.js、TypeScript、Java、.NET。
容器要求 仅限 Linux(linux/amd64)。 不支持特权容器。 不支持容器化服务器。
依赖 所有依赖项都必须位于容器映像中。 不支持 OS 级依赖项(如 Playwright)。
状态 仅限无状态。 仅限无状态。
UVX/NPX 支持。 不支持。 启动命令npx不被支持。

后续步骤