Overview
In this guide, you can learn how to connect your agent to remote Model Context Protocol (MCP) servers. The Atlas Agent Engine discovers tools from configured MCP servers at startup and makes them available to your agent code.
MCP server configuration is identical for Python and TypeScript agents. Only the agent code differs. Python agents access tools by using the app.get_tools() method and don't require any @app.tool() decorators. TypeScript agents access tools by using the app.getTools() method.
The Atlas Agent Engine supports the Streamable HTTP MCP transport and provides two methods to authenticate with remote MCP servers:
Bearer token (
bearer_envvalue): The platform reads a static token from an environment variable and attaches it as anAuthorization: Bearerheader on every request.OAuth 2.1 (
oauthvalue): The platform uses a token cache populated by theagentengine dev mcp auth logincommand and refreshes access tokens automatically when they expire.
You can use either or both authentication methods in the same file. Each server in the mcp.servers section specifies its own authentication method independently, so you can connect to a bearer-authenticated server and an OAuth-authenticated server in the same agent.yaml file.
Prerequisites
Before you begin, ensure that you have the following:
The
agentengineCLI installed and authenticated. To learn more, see the Install and Authenticate guide.A valid agent project with an
agent.yamlfile. To learn more, see the Create a Project guide.Credentials for your remote MCP server: a personal access token for bearer token authentication, or an account with OAuth access for OAuth authentication.
Configure Bearer Token Authentication
Use bearer token authentication when the MCP server accepts a static personal access token.
Add your token to the .env file.
Add the bearer token to your .env file with the variable name you will reference in the agent.yaml file. The following example shows how to add a token to your .env file:
GITHUB_MCP_TOKEN=<your-personal-access-token>
Important
Do not commit secrets to version control. Add the .env file to your .gitignore file.
Configure the MCP server in the agent.yaml file.
Add an mcp.servers section to your agent.yaml file. Set the auth.type field to the bearer_env value and the auth.token_env field to the name of the environment variable that holds the token. The following example shows how to configure a GitHub MCP server in your agent.yaml file:
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
Configure OAuth Authentication
Use OAuth authentication when the MCP server supports OAuth 2.1. You must run the agentengine dev mcp auth login command to populate the token cache before starting the agent stack.
Configure the MCP server in the agent.yaml file.
Add an mcp.servers section to your agent.yaml file. Set the auth.type field to the oauth value and provide the required OAuth scope. The following example shows how to configure an MCP server in your agent.yaml file:
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
Authenticate with the MCP server.
From your agent project directory, run the agentengine dev mcp auth login command with the server name you defined in the agent.yaml file. The command opens the OAuth consent flow in your browser and writes the token cache to the ~/.agentengine/mcp-oauth directory:
agentengine dev mcp auth login sentry
The token cache is separate for each project and each MCP endpoint. Logging in from one project does not log you in for another project, so you must run the agentengine dev mcp auth login command once per project.
During login, the CLI discovers the server's OAuth authorization endpoint. This endpoint must use the https scheme. If the server advertises an authorization endpoint that uses any other scheme, the agentengine dev mcp auth login command stops and generates a Refused to open unauthorized MCP OAuth URL error.
Note
You must run the agentengine dev mcp auth login command before running the agentengine dev up command. The runtime mounts the token cache at startup and cannot authenticate after the environment is running.
Write Agent Code
You don't need to define custom tools for agents that use remote MCP servers. Instead, use the following methods to access the tools discovered from all configured MCP servers:
Python:
app.get_tools()andapp.get_tool_schemas()methodsTypeScript:
app.getTools()andapp.getToolSchemas()methods
The following examples show a minimal deployable agent that uses remote MCP tools. The agent uses a LangGraph StateGraph to route messages between the LLM and the MCP tools. The LLM decides which tool to call, the ToolNode class executes the tool call, and the result is passed back to the LLM until no further tool calls are needed.
Select the tab for your agent's language to view the corresponding example:
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();
Set the language field in your agent.yaml file to the typescript value and point the entrypoint field at the exported app object, as in the remote_mcp_ts.github:app value.
Server Naming Rules
A server name is a key under the mcp.servers section. A name can contain up to 128 characters of printable UTF-8-encoded text, including non-ASCII characters and dotted names. A name cannot be empty or contain the following elements:
Whitespace-only text
Leading or trailing whitespace
Control, zero-width, byte order mark (BOM), or bidirectional characters
Path separators (
/or\)..
The agentengine agent validate command validates names against these rules. To learn more, see Validate Configuration.
MCP Server Configuration Schema
The following table describes the fields available in the mcp.servers section of your agent.yaml file:
Field | Type | Required | Description |
|---|---|---|---|
| object | no | Defines a named MCP server connection. The name is used as the server identifier when running the |
| string | no | Transport protocol for the MCP connection. Currently, the only supported value is |
| string | yes | URL of the remote MCP server endpoint. You must specify an absolute |
| map[string, string] | no | Static HTTP headers to include with every request to the MCP server. Use this for server-specific options such as filtering the available tool sets. |
| string | no | Authentication type. Accepted values are |
| string | when | Name of the environment variable that holds the bearer token. The variable must be set in your |
| string | no | Space-separated OAuth scopes to request. You can set this field only when |
| string | no | Human-readable name for the OAuth client. Some servers display this name on the authorization consent screen. You can set this field only when |
| string | no | Loopback redirect URI used by the interactive OAuth login. You can set this field only when |
| string | yes, if | Name of the environment variable that holds the OAuth client ID. |
| string | yes, if | Name of the environment variable that holds the OAuth client secret. |
| string | no | OAuth token endpoint used to request an access token for client credentials authentication. You must specify an absolute |
| list[string] | no | Allowlist of remote MCP tool names to expose to the agent. When set, the platform registers only the listed tools and ignores all other tools the server returns. When omitted, the platform exposes all tools the server returns. Use this field to limit the tool surface to only the tools your agent requires. |
| int | no | Request timeout in seconds applied to each MCP tool call. Defaults to |
Connect Multiple MCP Servers
You can define multiple servers within the mcp.servers section in a single agent.yaml file. The Atlas Agent Engine connects to all configured servers at startup and merges their tools into the agent's tool surface. The following example connects GitHub, Sentry, and Glean servers simultaneously in a single agent.yaml file:
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
When you connect to multiple servers with OAuth authentication, you must run the agentengine dev mcp auth login <name> command for each OAuth server before starting the environment. The following example shows the commands to run from your agent project directory to authenticate with both the Sentry and Glean servers before starting the environment:
agentengine dev mcp auth login sentry agentengine dev mcp auth login glean agentengine dev up
Provision MCP Credentials for Deployment
The .env file and the local OAuth token cache are only available during local development with the agentengine dev up command. Before you deploy your agent, you must provision MCP credentials as workspace secrets so the deployed runtime can authenticate with each MCP server.
The following sections describe how to provision secrets for each authentication type. To learn more about provisioning secrets, see the Provision Cloud Secrets guide.
Bearer Token Authentication
For each bearer-authenticated server, provision the token environment variable as a workspace secret. Use the following command to provision the secret and include the --workspace-scope flag to target the current workspace:
agentengine secret set GITHUB_MCP_TOKEN --workspace-scope
To provision the secret and sync it to running deployments in a single step, use the --sync flag:
agentengine secret set GITHUB_MCP_TOKEN --workspace-scope --sync
Run this command for each bearer-authenticated server before deploying.
OAuth Authentication
For each OAuth server, upload the local token cache to the workspace using the agentengine dev mcp auth upload command:
agentengine dev mcp auth upload sentry
To upload and sync to running deployments in a single step, use the --sync flag:
agentengine dev mcp auth upload sentry --sync
Run this command for each OAuth server before deploying.
Next Steps
After your agent is connected to remote MCP servers, you can test it locally and then deploy it. To learn more about testing your agent locally and deploying it, see the following guides in the Atlas Agent Engine documentation: