The MCP server internals in the OpenAI Agents SDK handle tool discovery, schema caching, approval policies, and safe credential handling across transport and exception layers. Tool snapshots are deep-copied to prevent cache mutation; approval policies flexibly support literals, per-tool mappings, and async callbacks; error chains and logs are scrubbed of credentials to prevent leakage.
AgentBase.get_mcp_tools calls MCPUtil.get_all_function_tools, passing the agent's MCP servers, schema conversion settings, run context, and the agent itself as arguments.[1]
In src/agents/mcp/server.py, _snapshot_tools() returns deep-copied MCPTool objects — via tool.model_copy(deep=True) — so callers cannot mutate cached tool schemas.[2]
RequireApprovalSetting in src/agents/mcp/server.py accepts a policy literal "always"/"never", a structured RequireApprovalObject, a per-tool dict mapping tool names to policies, a LocalMCPApprovalCallable, a plain bool, or None.[2] LocalMCPApprovalCallable in src/agents/mcp/server.py is a Callable[[RunContextWrapper[Any], AgentBase, MCPTool], MaybeAwaitable[bool]] — it can be synchronous or asynchronous.[2]
_safe_transport_cause() in src/agents/mcp/server.py returns None — suppressing the error cause chain — for any HTTPX transport error whose URLs are not credential-safe, or that already carries a __cause__, __context__, or __notes__, preventing credential leakage via exception chaining.[2] _credential_safe_exception_group() in src/agents/mcp/server.py recursively replaces a BaseExceptionGroup with fixed-data nodes, substituting Exception leaves with RuntimeError(_SAFE_EXCEPTION_MESSAGE), so control-flow semantics are preserved while all credential-bearing error details are scrubbed.[2] _log_transport_warning() in src/agents/mcp/server.py suppresses the transport exception object from the log entirely when the URL is not credential-safe, emitting only the bare message string to avoid accidental credential exposure in logs.[2] When _debug.DONT_LOG_TOOL_DATA is set in src/agents/mcp/server.py, transport warnings are passed directly to log_tool_action_warning with the full error object, bypassing the credential-safety check.[2]
src/agents/mcp/server.py loads StreamableHTTPTransport and streamablehttp_client dynamically from mcp.client.streamable_http at import time, supporting both MCP v1 and v2 without hard import failures.[2]
Sources