MCP and Connectors: Connecting External Services
On this page
Updated November 2, 2026 — Agent Builder. On June 3, 2026, OpenAI announced the shutdown of Agent Builder, scheduled for November 30, 2026; ChatKit remains available. Moving forward, OpenAI directs users to the Agents SDK or ChatGPT workspace agents. Since September 10, 2026, OpenAI has offered a public beta Agents API that hosts agent orchestration (see ChatGPT in 2026, Lesson 10).
MCP and Connectors: Connecting External Services
The Model Context Protocol (MCP) is an open standard that lets your agent connect to external services in a standardized way. Instead of rewriting integrations for every service, you plug in an MCP server, and your agent instantly gains new tools. Where you might have written three hundred lines of GitHub client code, you now need only a single server declaration.
What Is MCP?
MCP is an open standard defining how a client—your agent—communicates with a server, meaning an external service. Each MCP server exposes tools your agent can use. The protocol handles transport, serialization, and tool discovery. This last feature is the most valuable for daily work: the agent queries the server to see what it can do, so you don’t have to maintain a list. The Agents SDK includes native MCP support and connects to any compatible server.
Connecting an MCP Server
The SDK provides the MCPServerStdio class for local servers that communicate via stdin/stdout—typically a Node process launched with npx.
from agents import Agent, Runner
from agents.mcp import MCPServerStdio
# Local MCP server (communicates via stdin/stdout)
file_server = MCPServerStdio(
name="File Manager",
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", "/path/to/folder"],
)
async def main():
async with file_server:
agent = Agent(
name="File Agent",
instructions="You manage files for the user.",
mcp_servers=[file_server],
)
result = await Runner.run(agent, "List the files in the root folder.")
print(result.final_output)
The async with block isn’t just decoration: it starts the server process, discovers its tools, and shuts it down cleanly when the block exits. An agent created outside this context won’t have any tools.
Remote MCP Servers via SSE
For hosted servers, use MCPServerSse and the SSE (Server-Sent Events) transport. The logic stays the same; only the URL and authentication headers change.
from agents.mcp import MCPServerSse
github_server = MCPServerSse(
name="GitHub",
url="https://mcp.github.com/sse",
headers={"Authorization": "Bearer ghp_your_token"},
)
async def main():
async with github_server:
agent = Agent(
name="DevOps Agent",
instructions="You manage GitHub repositories.",
mcp_servers=[github_server],
)
result = await Runner.run(
agent,
"Create an issue in the my-project repo with the title 'Critical Bug'"
)
print(result.final_output)
OpenAI Connectors
In addition to MCP, OpenAI offers connectors managed directly on the platform. They integrate into Agent Builder and remain usable via the SDK without requiring you to host a server.
from agents import Agent, Runner
# Connectors configured in Agent Builder are automatically available
agent = Agent(
name="CRM Agent",
instructions="""You are a CRM assistant. Use the connectors
to access Salesforce, HubSpot, and Google Workspace.""",
model="gpt-5.6-terra",
# Connectors are linked to the agent's configuration on the platform
)
The absence of an mcp_servers parameter makes sense: connectors are tied to the agent’s configuration on the platform. They handle OAuth authentication, pagination, and rate limiting for you—three areas that consume significant time when handled manually.
Combining MCP and Function Tools
You don’t have to choose. A single agent can use an MCP server for data access and your own functions for business logic you don’t want to delegate.
from agents import Agent, Runner, function_tool
from agents.mcp import MCPServerStdio
@function_tool
def calculate_invoice(amount_excl_tax: float, vat_rate: float = 20.0) -> str:
"""Calculates the total amount including tax for an invoice."""
amount_incl_tax = amount_excl_tax * (1 + vat_rate / 100)
return f"Excl. tax: €{amount_excl_tax}, VAT {vat_rate}%: €{amount_excl_tax * vat_rate / 100:.2f}, Incl. tax: €{amount_incl_tax:.2f}"
db_server = MCPServerStdio(
name="Database",
command="npx",
args=["-y", "@modelcontextprotocol/server-postgres", "postgresql://user:pass@localhost/mydb"],
)
async def main():
async with db_server:
agent = Agent(
name="Accounting Agent",
instructions="""You handle accounting.
Use the database for customer data
and the calculation function for invoices.""",
tools=[calculate_invoice],
mcp_servers=[db_server],
)
result = await Runner.run(
agent,
"Retrieve orders for customer Alice and calculate the total invoice"
)
print(result.final_output)
VAT calculation stays in your code, where it’s testable and auditable; order retrieval goes through the PostgreSQL MCP server. That’s the split you should aim for.
Filtering MCP Tools
An MCP server can expose dozens of tools, most of which won’t matter for your use case—and each one consumes context and increases the risk of an inappropriate call. Start by inspecting what’s actually available.
server = MCPServerStdio(
name="GitHub",
command="npx",
args=["-y", "@modelcontextprotocol/server-github"],
)
# You can filter during connection
async with server:
tools = await server.list_tools()
# Inspect available tools
for tool in tools:
print(f"- {tool.name}: {tool.description}")
Handling MCP Errors
An MCP server is a process or remote service: it might fail to start, lose its connection, or have an expired token. Plan for a degraded mode instead of letting the exception bubble up to the user.
from agents.mcp import MCPServerStdio
async def create_agent_with_mcp():
server = MCPServerStdio(
name="External Service",
command="npx",
args=["-y", "my-mcp-server"],
)
try:
async with server:
agent = Agent(
name="My Agent",
instructions="Use the external service.",
mcp_servers=[server],
)
result = await Runner.run(agent, "Execute the task.")
return result.final_output
except Exception as e:
# Fallback without MCP
fallback_agent = Agent(
name="My Agent (degraded mode)",
instructions="The external service is unavailable. Inform the user.",
)
result = await Runner.run(fallback_agent, "The service is unavailable.")
return result.final_output
The fallback agent doesn’t pretend to work: it announces the unavailability. An agent that invents a response when its data source is down costs far more than one that admits it can’t proceed.
Key Takeaways
- MCP is an open protocol for connecting external services to your agent
- Use
MCPServerStdiofor local servers andMCPServerSsefor remote servers - OpenAI Connectors are managed integrations on the platform
- You can combine function tools and MCP servers in the same agent
- Handle MCP connection errors with a degraded mode