Overview
在本指南中,您可以学习;了解如何将代理连接到远程模型上下文协议 (MCP) 服务器。 Atlas Agent Engine 在初创企业时从配置的 MCP 服务器中发现工具,并使它们可供代理代码使用。
Python和 TypeScript 代理的 MCP服务器配置相同。只有代理代码不同。 Python代理使用 app.get_tools() 方法访问权限工具,不需要任何 @app.tool() 装饰器。 TypeScript 代理使用 app.getTools() 方法访问权限工具。
Atlas Agent Engine 支持 Streamable HTTP MCP 传输,并提供两种与远程 MCP 服务器进行身份验证的方法:
持有者令牌(
bearer_env值):平台从环境变量中读取静态令牌,并将其作为Authorization: Bearer标头附加到每个请求中。OAuth 2.1(
oauth值):平台使用由agentengine dev mcp auth login命令填充的令牌缓存,并在访问权限令牌过期时自动刷新这些令牌。
您可以在同一文件中使用其中一种或两种身份验证方法。 mcp.servers 部分中的每个服务器独立指定自己的身份验证方法,因此您可以在同一 agent.yaml文件中连接到持有者身份验证的服务器和 OAuth 身份验证的服务器。
先决条件
在开始之前,请确保您具备以下内容:
远程 MCP服务器的档案:用于不记名令牌身份身份验证的个人访问权限令牌,或用于 OAuth身份验证的具有 OAuth访问权限的帐户。
配置持有者令牌身份验证
当 MCP服务器接受静态个人访问权限令牌时,使用不记名令牌身份验证。
在 agent.yaml文件中配置 MCP服务器。
在 agent.yaml文件中添加 mcp.servers 部分。将 auth.type字段设置为 bearer_env 值,并将 auth.token_env字段设置为保存令牌的环境变量的名称。以下示例展示了如何在 agent.yaml文件中配置 GitHub MCP服务器:
mcp: servers: github: transport: streamable_http url: https://api.githubcopilot.com/mcp/ headers: X-MCP-Readonly: "true" X-MCP-Toolsets: repos,issues,pull_requests,actions auth: type: bearer_env token_env: GITHUB_MCP_TOKEN timeout_seconds: 30
配置 OAuth 身份验证
当 MCP服务器支持 OAuth 2.1 时,使用 OAuth身份验证。在启动代理堆栈之前,必须运行agentengine dev mcp auth login 命令来填充令牌缓存。
在 agent.yaml文件中配置 MCP服务器。
在 agent.yaml文件中添加 mcp.servers 部分。将 auth.type字段设置为 oauth 值,并提供所需的 OAuth 范围。以下示例展示了如何在 agent.yaml文件中配置 MCP服务器:
mcp: servers: sentry: transport: streamable_http url: https://mcp.sentry.dev/mcp auth: type: oauth scope: "org:read project:read team:read event:read" timeout_seconds: 30
使用 MCP服务器进行身份验证。
在代理项目目录中,使用您在 agent.yaml文件中定义的服务器名称运行agentengine dev mcp auth login 命令。该命令会在浏览器中打开 OAuth 同意流程,并将令牌缓存写入 ~/.agentengine/mcp-oauth目录:
agentengine dev mcp auth login sentry
每个项目和每个 MCP 端点的令牌缓存都是独立的。从一个项目登录不会日志另一项目,因此您必须为每个项目运行一次 agentengine dev mcp auth login 命令。
登录期间, CLI会发现服务器的 OAuth授权端点。此端点必须使用 https 方案。如果服务器公布使用任何其他方案的授权端点,则 agentengine dev mcp auth login 命令会停止并生成 Refused to open unauthorized MCP OAuth URL 错误。
注意
必须先运行agentengine dev mcp auth login 命令,然后才能运行agentengine dev up 命令。运行时在初创企业安装令牌缓存,在环境运行后无法进行身份验证。
写入代理代码
您无需为使用远程 MCP 服务器的代理定义自定义工具。相反,请使用以下方法访问权限从所有已配置的 MCP 服务器中发现的工具:
Python:
app.get_tools()和app.get_tool_schemas()方法TypeScript:
app.getTools()和app.getToolSchemas()方法
以下示例显示了使用远程 MCP 工具的最小可部署代理。该代理使用 LangGraph StateGraph 在 LLM 和 MCP 工具之间路由消息。 LLM 决定调用哪个工具,ToolNode 类执行工具调用,并将结果传递回 LLM,直到不需要进一步的工具调用。
选择客服人员语言对应的标签页,查看相应示例:
from typing import Annotated, TypedDict from langchain_core.messages import BaseMessage from langchain_openai import ChatOpenAI from langgraph.graph import END, START, StateGraph from langgraph.graph.message import add_messages from langgraph.prebuilt import ToolNode from agent_engine_sdk_langgraph import App app = App(app_name="my-mcp-agent") class AgentState(TypedDict): messages: Annotated[list[BaseMessage], add_messages] def build_agent(): llm = app.llm(ChatOpenAI(model="gpt-4o-mini")) tools = app.get_tools() llm_with_tools = llm.bind_tools(app.get_tool_schemas()) def call_model(state: AgentState): return {"messages": [llm_with_tools.invoke(state["messages"])]} def should_continue(state: AgentState): last = state["messages"][-1] return "tools" if getattr(last, "tool_calls", None) else "end" graph = StateGraph(AgentState) graph.add_node("agent", call_model) graph.add_node("tools", ToolNode(tools)) graph.add_edge(START, "agent") graph.add_conditional_edges( "agent", should_continue, {"tools": "tools", "end": END} ) graph.add_edge("tools", "agent") return graph.compile(checkpointer=app.checkpointer()) app.run()
import "dotenv/config"; import { BaseMessage } from "@langchain/core/messages"; import { Annotation, END, START, StateGraph } from "@langchain/langgraph"; import { ToolNode } from "@langchain/langgraph/prebuilt"; import { ChatOpenAI } from "@langchain/openai"; import { App } from "@mongodb-js/agent-engine-sdk-langgraph"; export const app = new App({ appName: "my-mcp-agent" }); const AgentStateAnnotation = Annotation.Root({ messages: Annotation<BaseMessage[]>({ reducer: (left, right) => left.concat(right), default: () => [], }), }); type AgentState = typeof AgentStateAnnotation.State; export const buildAgent = app.entrypoint(() => { const llm = app.llm(new ChatOpenAI({ model: "gpt-4o-mini" })); const tools = [...app.getTools()]; const llmWithTools = llm.bindTools([...app.getToolSchemas()]); const callModel = async (state: AgentState) => { const response = await llmWithTools.invoke(state.messages); return { messages: [response] }; }; const shouldContinue = (state: AgentState) => { const last = state.messages[state.messages.length - 1]; const toolCalls = (last as { tool_calls?: unknown[] }).tool_calls; return Array.isArray(toolCalls) && toolCalls.length > 0 ? "tools" : END; }; return new StateGraph(AgentStateAnnotation) .addNode("agent", callModel) .addNode("tools", new ToolNode(tools)) .addEdge(START, "agent") .addConditionalEdges("agent", shouldContinue, { tools: "tools", [END]: END, }) .addEdge("tools", "agent") .compile({ checkpointer: app.checkpointer() }); }); app.run();
将 agent.yaml文件中的 language字段设置为 typescript 值,并将 entrypoint字段点导出的 app对象,如 remote_mcp_ts.github:app 值中所示。
服务器命名规则
服务器名称是 mcp.servers 部分下的键。名称最多可包含 128 个字符的可打印 UTF-8 编码文本,包括非 ASCII 字符和点名称。名称不能为空或包含以下元素:
仅限空格的文本
前导或尾随空格
控制字符、零宽度字符、字节顺序标记 (BOM) 或双向字符
路径分隔符(
/或\)..
agentengine agent validate 命令根据这些规则验证名称。要学习;了解更多信息,请参阅验证配置。
MCP 服务器配置模式
下表描述了 agent.yaml文件的 mcp.servers 部分中的可用字段:
字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| 对象 | no | |
| 字符串 | no | MCP 连接的传输协议。目前,唯一支持的值为 |
| 字符串 | 是 | 远程 MCP服务器端点的URL 。您必须指定绝对 |
| map[string, string] | no | 对 MCP服务器的每个请求中包含的静态HTTP 头部。将其用于特定于服务器的选项,例如筛选可用工具集。 |
| 字符串 | no | 身份验证类型。接受的值为 |
| 字符串 | 当 | 保存持有者令牌的环境变量的名称。该变量必须在 |
| 字符串 | no | 以空格分隔的 OAuth 范围,用于请求。仅当 |
| 字符串 | no | OAuth客户端的人类可读名称。某些服务器会在授权同意屏幕上显示此名称。仅当 |
| 字符串 | no | 交互式 OAuth 登录使用的环回重定向 URI。仅当 |
| 字符串 | 是,如果 | 保存 OAuth客户端ID的环境变量的名称。 |
| 字符串 | 是,如果 | 保存 OAuth客户端密钥的环境变量的名称。 |
| 字符串 | no | OAuth 令牌端点,用于请求用于客户端凭证身份验证的访问权限令牌。您必须指定绝对 |
| list[string] | no | 要向代理公开的远程 MCP 工具名称的允许列表。设立为 后,平台仅注册列出的工具,而忽略服务器返回的所有其他工具。省略时,平台会公开服务器返回的所有工具。使用此字段可将工具界面限制为仅使用代理所需的工具。 |
| int | no | 应用于每个 MCP 工具调用的请求超时(以秒为单位)。默认为 |
连接多个 MCP 服务器
您可以在单个 agent.yaml文件的 mcp.servers 部分定义多个服务器。 Atlas Agent Engine 在初创企业时连接到所有已配置的服务器,并将其工具合并到助手的工具界面中。以下示例在单个 agent.yaml文件中同时连接 GitHub、Sentry 和 Glean 服务器:
mcp: servers: github: transport: streamable_http url: https://api.githubcopilot.com/mcp/ headers: X-MCP-Readonly: "true" X-MCP-Toolsets: repos,issues,pull_requests,actions auth: type: bearer_env token_env: GITHUB_MCP_TOKEN timeout_seconds: 30 sentry: transport: streamable_http url: https://mcp.sentry.dev/mcp auth: type: oauth scope: "org:read project:read team:read event:read" timeout_seconds: 30 glean: transport: streamable_http url: https://mongodb-be.glean.com/mcp/default auth: type: oauth scope: "SEARCH DOCUMENTS ENTITIES" client_name: My Glean MCP Agent timeout_seconds: 30
当您使用 OAuth身份验证连接到多个服务器时,必须在启动环境之前为每个 OAuth服务器运行agentengine dev mcp auth login <name> 命令。以下示例显示了在启动环境之前从代理项目目录运行的命令,以便与 Sentry 和 Glean 服务器进行身份验证:
agentengine dev mcp auth login sentry agentengine dev mcp auth login glean agentengine dev up
为部署预配 MCP 档案
.env文件和本地 OAuth 令牌缓存仅在本地开发期间使用 agentengine dev up 命令可用。在部署代理之前,必须将 MCP凭证预配为工作区密钥,以便部署的运行时可以通过每个 MCP服务器进行身份验证。
以下部分介绍如何为每种身份验证类型预配密钥。要学习;了解有关预配密钥的更多信息,请参阅预配 Cloud 密钥指南。
持有者令牌身份验证
对于每个经过持有者身份验证的服务器,将令牌环境变量设置为工作区密钥。使用以下命令预配密钥并包含 --workspace-scope 标志以针对当前工作区:
agentengine secret set GITHUB_MCP_TOKEN --workspace-scope
要在一个步骤中预配密钥并将其同步到运行的部署,请使用 --sync 标志:
agentengine secret set GITHUB_MCP_TOKEN --workspace-scope --sync
在部署之前,为每个经过持有者身份验证的服务器运行此命令。
OAuth 身份验证
对于每个 OAuth服务器,使用 agentengine dev mcp auth upload 命令将本地令牌缓存上传到工作区:
agentengine dev mcp auth upload sentry
要一步上传并同步到运行的部署,请使用 --sync 标志:
agentengine dev mcp auth upload sentry --sync
在部署之前,为每个 OAuth服务器运行此命令。
后续步骤
将代理连接到远程 MCP 服务器后,您可以在本地进行测试,然后部署。要学习;了解有关在本地测试和部署代理的更多信息,请参阅Atlas Agent Engine 文档中的以下指南: