将 MCP 工具与代理配合使用

模型上下文协议是一种开放标准,用于定义应用程序如何向大型语言模型(LLM)提供工具和上下文数据。 它支持将外部工具与模型工作流的一致、可缩放集成。

Microsoft代理框架支持与模型上下文协议 (MCP) 服务器集成,使代理可以访问外部工具和服务。 本指南演示如何连接到 MCP 服务器,并在代理中使用其工具。

使用第三方 MCP 服务器的注意事项

使用模型上下文协议服务器受你和服务提供商之间的条款的约束。 连接到非Microsoft服务时,某些数据(如提示内容)将传递给非Microsoft服务,或者应用程序可能会从非Microsoft服务接收数据。 您负责使用非微软服务和数据,并承担与该使用相关的任何费用。

你决定与本文中所述的 MCP 工具一起使用的远程 MCP 服务器是由第三方创建的,而不是Microsoft。 Microsoft尚未测试或验证这些服务器。 Microsoft对您或其他人使用任何远程MCP服务器不承担任何责任。

建议仔细查看和跟踪添加到基于代理框架的应用程序的 MCP 服务器。 我们还建议你依赖于受信任的服务提供商本身托管的服务器,而不是代理。

MCP 工具允许你传递远程 MCP 服务器可能需要的自定义标头,例如身份验证密钥或架构。 建议查看与远程 MCP 服务器共享的所有数据,并记录数据以进行审核。 了解与数据保留和位置相关的非Microsoft操作惯例。

重要

可以通过在每个运行时将每个运行标头包含在工具资源中来指定每个运行标头,或者在Python本地 MCP 工具上配置header_provider它们。 查看与远程 MCP 服务器共享的任何 API 密钥、OAuth 访问令牌或其他凭据。

有关 MCP 安全性的详细信息,请参阅:

代理框架的 .NET 版本可与 官方 MCP C# SDK 一起使用,以允许代理调用 MCP 工具。

以下示例演示如何:

  1. 设置和 MCP 服务器
  2. 从 MCP 服务器检索可用工具的列表
  3. 将 MCP 工具转换为 AIFunction's,以便可以将其添加到代理
  4. 使用函数调用从代理调用工具

设置 MCP 客户端

首先,创建连接到所需 MCP 服务器的 MCP 客户端:

using ModelContextProtocol.Client;

// Create an MCPClient for the GitHub server
await using var mcpClient = await McpClient.CreateAsync(new StdioClientTransport(new()
{
    Name = "MCPServer",
    Command = "npx",
    Arguments = ["-y", "--verbose", "@modelcontextprotocol/server-github"],
}));

在本示例中:

  • 名称:MCP 服务器连接的友好名称
  • 命令:运行 MCP 服务器的可执行文件(此处使用 npx 运行 Node.js 包)
  • 参数:传递给 MCP 服务器的命令行参数

检索可用工具

连接后,检索 MCP 服务器提供的工具列表:

// Retrieve the list of tools available on the GitHub server
var mcpTools = await mcpClient.ListToolsAsync().ConfigureAwait(false);

该方法 ListToolsAsync() 返回 MCP 服务器公开的工具集合。 这些工具会自动转换为代理可以使用的 AITool 对象。

使用 MCP 工具创建代理

在初始化期间创建代理并提供 MCP 工具:

using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

AIAgent agent = new AIProjectClient(
    new Uri(endpoint),
    new DefaultAzureCredential())
     .AsAIAgent(
         model: deploymentName,
         instructions: "You answer questions related to GitHub repositories only.",
         tools: [.. mcpTools.Cast<AITool>()]);

Warning

DefaultAzureCredential 对于开发来说很方便,但在生产中需要仔细考虑。 在生产环境中,请考虑使用特定凭据(例如), ManagedIdentityCredential以避免延迟问题、意外凭据探测以及回退机制的潜在安全风险。

要点:

  • 说明:提供与 MCP 工具功能相符的明确说明
  • 工具:将 MCP 工具强制转换为 AITool 对象并将其分散到工具数组中
  • 代理将自动访问 MCP 服务器提供的所有工具

使用代理

配置后,代理可以自动使用 MCP 工具来满足用户请求:

// Invoke the agent and output the text result
Console.WriteLine(await agent.RunAsync("Summarize the last four commits to the microsoft/semantic-kernel repository?"));

代理将:

  1. 分析用户的请求
  2. 确定需要哪些 MCP 工具
  3. 通过 MCP 服务器调用相应的工具
  4. 将结果合成为一致的响应

环境配置

请确保设置所需的环境变量:

var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ??
    throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";

资源管理

始终正确处理 MCP 客户端资源:

await using var mcpClient = await McpClient.CreateAsync(...);

使用 await using 可确保 MCP 客户端连接在超出范围时正确关闭。

常见 MCP 服务器

常用的 MCP 服务器包括:

  • @modelcontextprotocol/server-github:访问 GitHub 存储库和数据
  • @modelcontextprotocol/server-filesystem:文件系统作
  • @modelcontextprotocol/server-sqlite:SQLite 数据库访问

每个服务器提供扩展代理功能的不同工具和功能。 通过此集成,代理可以无缝访问外部数据和服务,同时维护模型上下文协议的安全性和标准化优势。

这样,代理就可以无缝访问外部工具和服务。

注释

在最少的 Python 安装中,可能需要手动安装 MCP 支持。 安装 mcp --pre 以使用 MCPStdioTool, MCPStreamableHTTPTool或 Agent.as_mcp_server()。 如果需要mcp[ws] --pre,请安装MCPWebsocketTool。

MCP 工具类型

代理框架支持三种类型的 MCP 连接:

MCPStdioTool - 本地 MCP 服务器

用于 MCPStdioTool 使用标准输入/输出连接到以本地进程身份运行的 MCP 服务器:

import asyncio
from agent_framework import Agent, MCPStdioTool
from agent_framework.openai import OpenAIChatClient

async def local_mcp_example():
    """Example using a local MCP server via stdio."""
    async with (
        MCPStdioTool(
            name="calculator",
            command="uvx",
            args=["mcp-server-calculator"]
        ) as mcp_server,
        Agent(
            client=OpenAIChatClient(),
            name="MathAgent",
            instructions="You are a helpful math assistant that can solve calculations.",
        ) as agent,
    ):
        result = await agent.run(
            "What is 15 * 23 + 45?",
            tools=mcp_server
        )
        print(result)

if __name__ == "__main__":
    asyncio.run(local_mcp_example())

MCPStreamableHTTPTool - HTTP/SSE MCP 服务器

用于 MCPStreamableHTTPTool 通过 HTTP 连接到 MCP 服务器并 Server-Sent 事件:

import asyncio
from agent_framework import Agent, MCPStreamableHTTPTool
from agent_framework.foundry import FoundryChatClient
from azure.identity.aio import AzureCliCredential

async def http_mcp_example():
    """Example using an HTTP-based MCP server."""
    async with AzureCliCredential() as credential:
        client = FoundryChatClient(credential=credential)
        async with (
            MCPStreamableHTTPTool(
                name="Microsoft Learn MCP",
                url="https://learn.microsoft.com/api/mcp",
            ) as mcp_server,
            Agent(
                client=client,
                name="DocsAgent",
                instructions="You help with Microsoft documentation questions.",
            ) as agent,
        ):
            result = await agent.run(
                "How to create an Azure storage account using az cli?",
                tools=mcp_server
            )
            print(result)

if __name__ == "__main__":
    asyncio.run(http_mcp_example())

创建的 HTTP 客户端 MCPStreamableHTTPTool 不会持久保存响应 Cookie。 如果服务器要求 Cookie 进行身份验证、会话或负载均衡器关联,请传递配置的 httpx.AsyncClient 身份验证 http_client=、 会话或负载均衡器相关性。 提供的客户端会保留其 Cookie 行为,并保留调用方拥有的行为。 将 Cookie 承载客户端及其 MCP 工具会话的范围限定为一个经过身份验证的主体。

对于经过身份验证的 HTTP 终结点,请 static_headers 用于固定凭据或 header_provider 从每个运行派生的值。 这两个路径仅将标头添加到配置源的请求,并从跨源重定向中删除它们。 创建工具且不序列化并发调用时,将复制固定标头。 当这两个选项都提供相同的标头时,来自 header_provider 的动态值优先。

在生成的工具调用期间, header_provider 仅接收运行主机 function_invocation_kwargs。 即使模型参数具有相同的名称,它也不会接收模型提供的工具参数。 直接 call_tool(...) 调用将其调用方提供的关键字参数传递给提供程序。 模型值仍可优先于单独合并的出站工具参数,但它们不控制身份验证标头。

固定标头和动态标头共同构成了 HTTP 会话的有效标识。 标头名称不区分大小写,而值仍区分大小写。 当服务器架构允许同名时,运行时关键字参数也有资格获得出站工具参数。 若要使凭据远离工具参数,请通过关闭或 ContextVar使用 static_headers或提供自定义 HTTP 客户端在提供程序中捕获凭据。

框架拥有的会话在连接时绑定此有效标识。 如果以后的运行生成不同的标识,该工具将在发送调用并刷新会话派生的工具并提示发现之前重新连接。 初始化、发现、后台 ping 和其他连接生存期请求继续使用绑定到该会话的标头。

调用方提供的会话仍然是调用方拥有的。 由于包装器无法为这些会话建立或重新连接未知标识,因此拒绝具有未知标识的动态标头解析。 更改的标识也会被拒绝;使用单独的框架托管工具实例。

如果该工具在运行前急切地连接,则提供程序会收到连接生存期请求的空映射。 在本例中捕获或刷新提供程序中的构造时凭据。 如果凭据仅在运行时到达,则传递 run(tools=[...]) 未连接的工具, function_invocation_kwargs 以便运行建立连接。

仅当没有将连接种子设定为运行种子时,才允许来自提供程序的一个 KeyError 提供程序,并且请求在不使用提供程序标头的情况下继续。 运行为连接设定种子后,缺少的键是配置错误,并显示异常。

按明确名称选择工具

设置 allowed_tools 或列出工具 approval_mode时,请使用原始远程工具名称或明确的前缀名称。 如果一个配置的名称与规范化后的多个原始远程名称匹配,则代理框架将 ToolExecutionException引发。 使用确切的原始名称或更改 tool_name_prefix 使本地名称唯一。

MCP 采样弃用

Warning

服务器启动的 MCP 采样,自 sampling_callback MCP 规范版本 2026-07-28 起弃用,删除时间不晚于 2027-07-28。 不要在此功能上生成新的集成。 MCP 服务器应直接调用模型提供程序 API。

控制主机有效负载保留

当主机传输(如 AG-UI)使用 MCP 工具结果时,代理框架会将完整的 JSON 安全结果与分析的面向模型的值分开保留。 这样,主机就可以接收字段,例如 structuredContent 不向模型历史记录添加仅限主机的数据。

在任何 tool_result_content MCP 传输上使用,在结果包含两者 content 时选择模型可见值,并且 structuredContent:

价值 模型可见的结果
structured_first 如果存在,content则使用 structuredContent 。 此值为默认值。
content_first 否则使用 nonemptycontentstructuredContent。
content_only structuredContent忽略 。
structured_only content忽略 。
both 追加在content块之后序列化structuredContent的。

此选择不会更改保留的主机有效负载。 parse_tool_results 重写选择策略。

默认情况下,每个 MCP 传输将保留的主机有效负载限制为 1 MiB。 从主机通道中省略超大有效负载,而分析的结果仍会到达模型。 对传输设置不同的正字节限制,或者仅在下游主机应用自己的绑定时使用 None :

mcp_server = MCPStreamableHTTPTool(
    name="Microsoft Learn MCP",
    url="https://learn.microsoft.com/api/mcp",
    max_host_payload_size_bytes=256 * 1024,
)

MCPWebsocketTool - WebSocket MCP 服务器

用于 MCPWebsocketTool 通过 WebSocket 连接连接到 MCP 服务器:

import asyncio
from agent_framework import Agent, MCPWebsocketTool
from agent_framework.openai import OpenAIChatClient

async def websocket_mcp_example():
    """Example using a WebSocket-based MCP server."""
    async with (
        MCPWebsocketTool(
            name="realtime-data",
            url="wss://api.example.com/mcp",
        ) as mcp_server,
        Agent(
            client=OpenAIChatClient(),
            name="DataAgent",
            instructions="You provide real-time data insights.",
        ) as agent,
    ):
        result = await agent.run(
            "What is the current market status?",
            tools=mcp_server
        )
        print(result)

if __name__ == "__main__":
    asyncio.run(websocket_mcp_example())

可与 Python 代理框架一起使用的常见 MCP 服务器:

  • 计算器: uvx mcp-server-calculator - 数学计算
  • 文件系统: uvx mcp-server-filesystem - 文件系统作
  • GitHub: npx @modelcontextprotocol/server-github - GitHub 存储库访问权限
  • SQLite: uvx mcp-server-sqlite - 数据库作

每个服务器提供不同的工具和功能,用于扩展代理的功能,同时维护模型上下文协议的安全性和标准化优势。

完整示例

# Copyright (c) Microsoft. All rights reserved.

import asyncio
import os

from agent_framework import Agent, MCPStreamableHTTPTool
from agent_framework.openai import OpenAIChatClient

"""
MCP Authentication Example

This example demonstrates a `header_provider` that authenticates both connection-time and tool-call requests.

For more authentication examples including OAuth 2.0 flows, see:
- https://github.com/modelcontextprotocol/python-sdk/tree/main/examples/clients/simple-auth-client
- https://github.com/modelcontextprotocol/python-sdk/tree/main/examples/servers/simple-auth
"""


async def api_key_auth_example() -> None:
    """Example of using API key authentication with MCP server."""
    mcp_server_url = os.getenv("MCP_SERVER_URL", "your-mcp-server-url")
    api_key = os.getenv("MCP_API_KEY")
    if not api_key:
        raise ValueError("MCP_API_KEY environment variable must be set.")

    async with Agent(
        client=OpenAIChatClient(),
        name="Agent",
        instructions="You are a helpful assistant.",
        tools=MCPStreamableHTTPTool(
            name="MCP tool",
            description="MCP tool description",
            url=mcp_server_url,
            header_provider=lambda _kwargs: {"Authorization": f"Bearer {api_key}"},
        ),
    ) as agent:
        query = "What tools are available to you?"
        print(f"User: {query}")
        result = await agent.run(query)
        print(f"Agent: {result.text}")

if __name__ == "__main__":
    asyncio.run(api_key_auth_example())

MCP 工具类型

此 mcptool 包允许代理使用模型上下文协议 (MCP) 服务器中的工具。

连接到 MCP 服务器

import (
    "github.com/microsoft/agent-framework-go/tool/mcptool"

    "github.com/modelcontextprotocol/go-sdk/mcp"
)

session, err := mcptool.Connect(ctx, &mcp.StreamableClientTransport{
    Endpoint: "https://learn.microsoft.com/api/mcp",
})
if err != nil {
    panic(err)
}
defer session.Close()

列出和使用 MCP 工具

tools, err := mcptool.ListTools(ctx, session)
if err != nil {
    panic(err)
}

a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
    Instructions: "You are a helpful assistant.",
    Config: agent.Config{
        Tools: tools,
    },
})

resp, err := a.RunText(ctx, "How to create an Azure storage account using az cli?").Collect()

支持的传输方式

  • HTTP/SSE - mcp.StreamableClientTransport{Endpoint: "https://..."}
  • Stdio - 启动本地 MCP 服务器进程

Tip

有关完整的可运行示例,请参阅 MCP 工具示例 。

将代理公开为 MCP 服务器

可以将代理公开为 MCP 服务器,允许它用作任何 MCP 兼容的客户端(例如 VS Code GitHub Copilot 代理或其他代理)的工具。 代理的名称和说明将成为 MCP 服务器元数据。

使用 .AsAIFunction()函数工具包装代理,创建 McpServerTool代理并将其注册到 MCP 服务器:

using System;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ModelContextProtocol.Server;

// Create the agent
AIAgent agent = new AIProjectClient(
    new Uri("<your-foundry-project-endpoint>"),
    new DefaultAzureCredential())
        .AsAIAgent(
            model: "gpt-4o-mini",
            instructions: "You are good at telling jokes.",
            name: "Joker");

// Convert the agent to an MCP tool
McpServerTool tool = McpServerTool.Create(agent.AsAIFunction());

// Set up the MCP server over stdio
HostApplicationBuilder builder = Host.CreateEmptyApplicationBuilder(settings: null);
builder.Services
    .AddMcpServer()
    .WithStdioServerTransport()
    .WithTools([tool]);

await builder.Build().RunAsync();

Warning

DefaultAzureCredential 对于开发来说很方便,但在生产中需要仔细考虑。 在生产环境中,请考虑使用特定凭据(例如), ManagedIdentityCredential以避免延迟问题、意外凭据探测以及回退机制的潜在安全风险。

安装所需的 NuGet 包:

dotnet add package Microsoft.Agents.AI.Foundry --prerelease
dotnet add package Microsoft.Extensions.Hosting
dotnet add package ModelContextProtocol

调用 .as_mcp_server() 代理以将其公开为 MCP 服务器:

注释

Python agent.as_mcp_server() 还依赖于可选 mcp 包。 如果使用精简/基于核心的安装,请先运行 pip install mcp --pre 。

from agent_framework.openai import OpenAIChatClient
from typing import Annotated

def get_specials() -> Annotated[str, "Returns the specials from the menu."]:
    return "Special Soup: Clam Chowder, Special Salad: Cobb Salad"

# Create an agent with tools
agent = OpenAIChatClient().as_agent(
    name="RestaurantAgent",
    description="Answer questions about the menu.",
    tools=[get_specials],
)

# Expose the agent as an MCP server
server = agent.as_mcp_server()

设置 MCP 服务器以侦听标准输入/输出:

import anyio
from mcp.server.stdio import stdio_server

async def run():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(read_stream, write_stream, server.create_initialization_options())

if __name__ == "__main__":
    anyio.run(run)

使用 包装代理 agenttool.New,使用 MCP 服务器 mcptool.AddTool注册代理,并通过 stdio 运行服务器:

import (
    "context"

    "github.com/microsoft/agent-framework-go/agent"
    "github.com/microsoft/agent-framework-go/provider/foundryprovider"
    "github.com/microsoft/agent-framework-go/tool/agenttool"
    "github.com/microsoft/agent-framework-go/tool/mcptool"
    "github.com/modelcontextprotocol/go-sdk/mcp"
)

jokeAgent := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
    Instructions: "You are good at telling jokes.",
    Config: agent.Config{
        Name:        "Joker",
        Description: "An agent that tells jokes.",
    },
})

server := mcp.NewServer(&mcp.Implementation{
    Name:    "agent-mcp-server",
    Version: "1.0.0",
}, nil)

mcptool.AddTool(server, agenttool.New(jokeAgent, agenttool.Config{}))

if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil {
    panic(err)
}

Tip

有关完整的可运行示例,请参阅 代理作为 MCP 工具示例 。

后续步骤