MCP With OpenAI Models: What Works Today
OpenAI supports the Model Context Protocol in four places: the Responses API’s MCP tool, the Agents SDK, ChatGPT and Codex. Who acts as the client in each, how sign-in and approvals work, what ChatGPT does with read-only hints, and which to pick.
8 min read
MCP works with OpenAI models in four places today. In the Responses API, you declare a remote MCP server as a tool and OpenAI’s own servers call it during the response. In the Agents SDK, your Python code is the MCP client, so it can reach local servers over stdio as well as remote ones. In ChatGPT, listed apps connect from Settings, and developer mode lets you add any remote MCP server yourself. In Codex, one config.toml holds the MCP servers its clients use. The question that separates them is who makes the call to your server: OpenAI’s infrastructure, your code, ChatGPT, or a tool on your machine. That decides what the server must be reachable from, where credentials live and who approves each call.
This page is the map. Step-by-step guides for particular tools are elsewhere: ChatGPT connectors for Jira, Notion MCP with ChatGPT, Trello MCP with ChatGPT and Codex CLI with a task board. OpenAI renames things often; this follows its documentation as it reads at the end of September 2026.
The four routes at a glance
- Responses API: OpenAI’s servers are the client. Your server must be reachable from the internet, or through OpenAI’s Secure MCP Tunnel. Your code approves calls.
- Agents SDK: your program is the client. Servers can be local processes or remote URLs, and your code holds the credentials.
- ChatGPT: ChatGPT is the client, on the web. Remote servers only, OAuth or no sign-in, and the person in the chat approves writes.
- Codex: the CLI and IDE extension are the client, with local stdio servers and remote HTTP servers configured in one file, and approvals set per server.
The Responses API: MCP as a hosted tool
In OpenAI’s MCP guide for the API (opens in a new tab), an MCP server is one more entry in the tools array, with type: "mcp", a server_label and a server_url. When the model decides to call a tool, the API itself sends the request to your server and puts the result in the model’s context. The API works with servers that speak Streamable HTTP or HTTP with SSE. For a private or on-premises server, the same guide describes a tunnel_id that reaches it through Secure MCP Tunnel without exposing it to the internet.
resp = client.responses.create(
model=MODEL,
input="What is in the In Progress lane?",
tools=[{
"type": "mcp",
"server_label": "board",
"server_url": "https://fenbs.ai/api/mcp",
"authorization": BOARD_TOKEN,
"allowed_tools": ["fenbs_list_items", "fenbs_get_item"],
"require_approval": "never",
}],
)- Tool lists are fetched once. The response carries an
mcp_list_toolsitem, and as long as it stays in the context, for example by passingprevious_response_id, the API does not ask your server for its tools again. - Approvals are on by default. The model’s intended call comes back as an
mcp_approval_request; you answer with anmcp_approval_response.require_approvalcan bealways,never, or a filter naming tools. Relax it only for tools you know are read-only. allowed_toolsimports only the tools you list, which shortens the list the model reads and keeps writes out of reach.- The
authorizationfield carries an OAuth access token for the server. OpenAI says the API does not store it, so you send it with every request. - Older built-in connectors such as Google Drive and Gmail used a
connector_id. OpenAI says that field is deprecated for models released after 1 September 2026, in favour ofserver_urlortunnel_id.
OpenAI’s warning in the same guide is worth quoting in substance: a malicious server can take anything that enters the model’s context. Connect to servers run by the service provider themselves, log what you send to third parties, and keep approvals on for anything that writes.
The Agents SDK: your code is the client
The Agents SDK’s MCP page (opens in a new tab) offers five ways in. HostedMCPTool hands the whole round trip to the Responses API, exactly as above. MCPServerStreamableHttp and MCPServerStdio make your own process the client, so the server can be a URL on your network or a program you launch; MCPServerSse still exists, but the SDK notes that MCP has deprecated SSE and recommends Streamable HTTP or stdio. MCPServerManager looks after several servers at once.
async with MCPServerStreamableHttp(
name="board",
params={
"url": "https://fenbs.ai/api/mcp",
"headers": {"Authorization": f"Bearer {token}"},
},
cache_tools_list=True,
) as server:
agent = Agent(name="Triage", instructions="Read the board; do not change it.",
mcp_servers=[server])
result = await Runner.run(agent, "Which bugs have been in To Do longest?")The SDK adds the controls a production agent needs. create_static_tool_filter takes allowed_tool_names or blocked_tool_names, and a callable filter can decide per run. cache_tools_list=True avoids asking the server for its tools every turn. require_approval supports human sign-off per tool, and servers that offer MCP prompts expose them through list_prompts() and get_prompt(). Choose the hosted tool when OpenAI can reach the server and you want less code; choose a local transport when the server is private or you want every call to pass through your process.
ChatGPT: listed apps and developer mode
Most people meet MCP in ChatGPT without seeing the word. Some of the apps you connect under Settings, Plugins are built on their maker’s MCP server; Atlassian Rovo, the app for Jira, is one. For a server with no listing, ChatGPT’s developer mode (opens in a new tab) adds any remote server yourself. OpenAI lists it for Pro, Plus, Business, Enterprise and Education accounts on the web, over SSE or streaming HTTP, with OAuth, no authentication or a mix. It calls developer mode powerful but dangerous, and asks for an understanding of prompt injection, mistaken writes and malicious servers first.
What readOnlyHint does in ChatGPT
The same page says ChatGPT respects the MCP readOnlyHint tool annotation, and treats any tool without it as a write action. Write actions ask for confirmation by default, showing the input that will be sent. You can remember an approve or deny choice for one tool for the rest of a conversation; a new conversation, or refreshing the same one, asks again. For people building a server, that makes the annotation practical rather than decorative: a search tool without readOnlyHint: true will stop the conversation for a confirmation every time it runs.
{
"name": "list_tasks",
"description": "List tasks on a board, filtered by lane.",
"inputSchema": { "type": "object", "properties": { "lane": { "type": "string" } } },
"annotations": { "readOnlyHint": true }
}Mark only what is truly read-only. The MCP specification treats annotations as hints a client must not trust from an untrusted server, and the three building blocks explains why. If you want your server to feed ChatGPT’s deep research or company knowledge, OpenAI’s server-building guide (opens in a new tab) asks for two read-only tools named search and fetch, with a fixed result shape.
Codex: one config file for its clients
Codex keeps MCP servers in ~/.codex/config.toml or a project’s .codex/config.toml, and the same configuration serves its command line, IDE extension and desktop app. It runs local stdio servers and remote Streamable HTTP servers, signs in to OAuth servers with codex mcp login, and reads a static token from the variable named in bearer_token_env_var. Per server, enabled_tools and disabled_tools trim the list, and default_tools_approval_mode chooses between auto, prompt, approve and writes, which asks only for tools the server has not marked read-only.
One change catches people following older tutorials. Codex used to run as an MCP server itself, so an Agents SDK program could drive it as a tool. OpenAI’s Codex documentation (opens in a new tab) now says the codex mcp-server command and the standalone binary have been removed, and points integrations at the Codex app server, which uses its own protocol rather than MCP. Codex remains an MCP client.
Which to pick
- A person wants to use a product from a chat window: ChatGPT, through the product’s listed app if it has one, developer mode if not.
- Your application should call a public MCP server during a response with little code: the Responses API’s MCP tool, with
allowed_toolsand approvals. - Your agent needs a private server, a local process or tight control of every call: the Agents SDK with Streamable HTTP or stdio.
- A developer wants the assistant in the terminal or editor: Codex, with servers in
config.toml.
Where a task board fits
fenbs is a remote MCP server at https://fenbs.ai/api/mcp, so all four routes can reach it. ChatGPT connects as a custom connector where your plan allows one, and Codex with codex mcp add and a browser sign-in; both hold your role on the board narrowed by the scopes you tick, and every change is recorded under the assistant’s name. The Responses API and the Agents SDK cannot open a browser, so they send a token you issue by hand under Settings, with a name, the scopes it needs and an optional expiry. A read-only token and a short allowed_tools list are a sensible first week.
Related
Connecting ChatGPT to a board: the ChatGPT integration. Codex: the Codex CLI integration. How the MCP route compares with a model’s own tools: MCP vs function calling. Before any server can write: MCP security best practices.