How to manage Codex MCP servers for your team
Nolan Sullivan
Published · 16 min read
TL;DR
Codex reads Model Context Protocol (MCP) servers from each developer's
config.toml. Admins can restrict which servers run with an mcp_servers
allowlist in the Admin Console's managed requirements. OpenAI's own docs say
an allowlist entry doesn't create the server configuration, and MCP telemetry
has to be set up separately. In the Speakeasy AI Control Plane, you grant a
role access to approved servers, and Speakeasy publishes them in that role's
plugin to a marketplace your ChatGPT workspace imports once. Each person signs
in to the servers that need it, and each call is logged with the person and
client.
To manage Codex MCP servers for a team, use two controls together. Codex's managed requirements decide which MCP servers may run on a developer's machine, through an mcp_servers allowlist that admins edit in the Admin Console. A control plane delivers the approved servers to each role through a plugin marketplace the ChatGPT workspace imports, prompts each person to sign in where a server needs it, and logs each call with the person and client.
By default, each developer adds each server to Codex by hand. Admins can narrow that with managed requirements and set starting defaults from the Admin Console, but OpenAI is direct about where the allowlist stops: "Allowing a server and configuring it are separate steps." The allowlist sets the boundary for what can run, and something else has to put the approved servers in front of the right people and show you what they call.
How does Codex load MCP servers by default?
OpenAI's MCP guide says Codex stores MCP configuration in config.toml, by default ~/.codex/config.toml. A developer can also scope servers to one trusted project with .codex/config.toml.
A developer adds a server in one of two ways:
- With the CLI.
codex mcp add <server-name> -- <stdio server-command>writes the entry, with--envflags for any environment variables the server needs. For a streamable HTTP server,--url <server-url>takes the place of the command. - In the file. A
[mcp_servers.<server-name>]table inconfig.tomlholds the command or URL and its options.
For servers that support OAuth, the developer signs in with codex mcp login <server-name>.
Each developer repeats those steps, and signs in, on their own machine. Speakeasy's rollout guide describes what that looks like across a team: "Each person configures each client by hand, nobody knows who has what, and removing access means chasing down local config files."
What can admins control in Codex natively?
OpenAI gives admins real controls over Codex, and a team rollout should start from them. Most of them live in Admin Console > Agent security, and they come in two kinds:
- Requirements are "admin-enforced constraints that users can't override."
- Configuration defaults are starting
config.tomlsettings that users can override.
As OpenAI puts it, "You don't need to distribute a local file to use cloud-managed settings." Workspace default sets the baseline, and Overrides apply "when specific users, groups, or roles need different settings."
Five controls bear on MCP:
- An MCP server allowlist. "If you configure an
mcp_serversallowlist, the client enables an MCP server only when both its name and identity match an approved entry; otherwise, the client disables it." HTTP servers match by URL (exact, prefix, or regex) and stdio servers by command, or by executable and arguments. - A deny-all switch. "If
mcp_serversis present but empty, the local client disables all MCP servers." OpenAI's security cookbook recommends starting there. - Plugin-bundled servers. Servers that arrive inside a plugin are allowlisted separately, with the same identity shapes, under
plugins.<plugin>.mcp_servers.<server>. - Marketplace source rules. Setting
restrict_to_allowed_sources = truewith one or more source rules makes Codex "reject unmatched marketplace add, plugin install, and configured Git marketplace refresh operations." - Workspace plugins. Admins can import a plugin marketplace from GitHub and set each plugin's Installation policy to Available or Installed for each eligible role.
The cookbook's allowlist entry for an HTTP server looks like this:
[mcp_servers.internal_docs]
identity = { url = "https://mcp.example.com/docs" }
Together, these let an admin enforce which servers and marketplaces Codex can use from the Admin Console. Restricting sign-in to the company workspace is a separate control, and it needs a local file or MDM.
What does the Codex MCP allowlist leave to you?
OpenAI's docs say plainly what the allowlist and import don't do. The gaps fall into three areas.
Delivery. An allowlist permits servers, but it doesn't install them. OpenAI's cookbook: "An allowlist entry permits a matching server; it does not create the server configuration. Configure the server separately with the matching name and identity, along with the authentication it requires." Each approved server still has to reach each developer who needs it, with the name and identity the allowlist expects. Workspace plugins can carry servers to members by role, but someone has to build the marketplace repository they come from and keep it in step with who should have what.
Sign-in. Importing a plugin into the workspace doesn't connect anyone to the services behind it. OpenAI's plugin docs: "Importing a plugin doesn't give members app access or connect their accounts." Each person still has to authenticate to each server that needs it.
Visibility and trust. The allowlist settles which servers can run, and leaves open whether they are safe and who calls their tools. The cookbook adds: "Identity allowlisting does not prove that a server's tools, upstream data, credentials, or launch environment are safe." For stdio servers, the matcher "does not constrain cwd, env, or env_vars", and local stdio processes run outside the local command sandbox. For monitoring, the cookbook tells admins to "configure separate telemetry for web search, apps, connectors, MCP servers, browser activity, and Codex Cloud."
So an admin who has set the allowlist still needs three things: a way to deliver the approved servers to the right people, a sign-in flow per person, and one place to see which tools each person called. A registry of approved MCP servers, delivered by role and logged per call, covers all three. In the Speakeasy AI Control Plane, one Team Access grant puts a server in the role's plugin and decides which tool calls succeed, OAuth servers prompt each person to sign in, and Tool Logs records each call with the person and client. Whether each server is safe to approve is still a review you run before you register it.
How to manage Codex MCP servers in Speakeasy, step by step
The steps below deliver approved servers to Codex with the Speakeasy AI Control Plane, then use Codex's requirements to keep anything else from running. Steps 1 and 2 happen in the Speakeasy dashboard. Step 3 starts there and moves to the ChatGPT workspace's Admin Console, where steps 4 and 5 also happen. Step 6 ends on developer machines, and step 7 checks the result in Codex and Speakeasy.
Servers travel in an agent plugin, one bundle per role. Once a ChatGPT workspace admin imports the marketplace that holds them, Speakeasy's OpenAI docs say its plugins are available to ChatGPT on web, desktop, and mobile, to Codex in the ChatGPT desktop app, and to the Codex CLI.
Before you start
- Speakeasy admin. Publishing the marketplace needs the
project:writescope and creating an API key needsorg:admin. The default Admin role holds both. - ChatGPT workspace admin. The OpenAI-side steps need a workspace admin account on a ChatGPT Business, Enterprise, or Edu workspace.
- GitHub account. The admin who imports the marketplace into ChatGPT needs one. Only that account needs repository access.
- A role for the team. Roles come from directory sync or are created under Organization settings > Team > Roles & Permissions.
Step 1: Register the MCP server
In the Speakeasy dashboard, open MCP Gateway > MCP and select Add new. Choose From the catalog for a reviewed third-party server, or Hosted remotely to enter an MCP server URL, which Verify connectivity checks before the server is created.
Finish its authentication setup before rolling it out. Register or build an MCP server covers each option.
Step 2: Grant the team's role Connect access
Open the server, select its Team Access tab, select Grant access > Role, and choose the team's role. Leave Connect set to All tools, or narrow it with Specific tools…. Remote servers publish no tool catalog, so they narrow by tool annotation, such as read-only or destructive, rather than by tool name.
The Connect grant distributes the server. Speakeasy adds it to every plugin in the project that's assigned to the role and requests a marketplace publish. Grant a role access shows how to check that the server reached the plugin.
The same grant decides which calls succeed later, because server authorization refuses tool calls a person's roles don't allow.
Step 3: Import the marketplace into ChatGPT
The marketplace is a private GitHub repository, so the importing admin needs access first. On MCP Gateway > Plugins, select Manage collaborators on the marketplace card and enter that admin's GitHub username, then have them accept the GitHub invitation. Copy the marketplace repository URL from the same page.
Then switch to ChatGPT. OpenAI reads the marketplace through the importing admin's own GitHub connection, so confirm that connection is to the account you just added. Open Admin > Plugins and select Add > Import marketplace:
- Source: the repository URL.
- Path: leave empty.
- Branch, tag, or commit: leave empty to track the default branch, so later publishes are picked up automatically.
The import steps, including the GitHub connection check, are in Speakeasy's OpenAI docs.
Step 4: Set the installation policy per role
Import doesn't carry the installation policy over from the repository, so set it here. In Admin > Plugins, select the role's plugin and set its Installation policy for each eligible workspace role:
- Installed deploys the plugin to everyone in the role without any action on their part.
- Available lists the plugin in the directory for members of the role to install themselves.
The installation policy scopes delivery on OpenAI surfaces, since Speakeasy's plugin assignments don't gate marketplace installs.
Do the same for the observability plugin, which is the prerequisite for most governance features on OpenAI surfaces, including usage observability and shadow MCP detection. Speakeasy's docs recommend Installed for a real rollout, since coverage gaps mean unobserved sessions.
Enable the MCP servers each plugin connects to. Set the installation policy has the details.
Step 5: Restrict Codex to approved servers and marketplaces
Steps 1 to 4 deliver the approved servers, and this optional step keeps any other server from running in Codex on developer machines. It uses OpenAI's documented allowlist for plugin-bundled MCP servers.
In the Admin Console, open Agent security, select Workspace default or an override, open Requirements, and select Edit as TOML:
- Allowlist the plugin's servers. Add each server in the role's plugin under
plugins.<plugin>.mcp_servers.<server>, with the same identity shape OpenAI uses for standalone servers. Once thepluginstable is present, Codex disables plugin-bundled servers without a matching entry. - Allowlist standalone servers. The
pluginstable covers only plugin-bundled servers, so add a top-levelmcp_serverstable too. Once it's present, Codex disables any configured server that doesn't match it. - Restrict marketplace sources. Set
restrict_to_allowed_sources = trueunder[marketplaces]and add agitsource rule for each marketplace you approve. OpenAI says these rules "limit which local or Git sources users can add and use," and that remotely installed workspace plugins are separate from the curated Git source policy. OpenAI's own curated Git marketplaces must also match a rule, so add one for them if your team uses those plugins.
[plugins.<plugin>.mcp_servers.<server>]
identity = { url = "<server-url>" }
The requirements.toml reference in OpenAI's docs has the full schema for both tables.
Step 6: Turn on Codex telemetry
The observability plugin's hooks cover sessions and tool calls on their own, but Codex's OpenTelemetry export associates Codex sessions with individual users and supplies token and cost detail. Without it, Codex activity arrives unattributed.
Back in Speakeasy, create an API key with the Hooks scope, then copy the endpoint and protocol values from the Install tab of the observability plugin's detail page on MCP Gateway > Plugins. On each developer machine, add them and the API key to the [otel] section of ~/.codex/config.toml, where Codex reads its telemetry settings. Configure Codex telemetry shows the full [otel] block.
To skip the per-machine edit for the Codex CLI, put the same [otel] block in the requirements from step 5. OpenAI's managed configuration docs say Codex CLI 0.166.0 reads [otel] from requirements.toml and that "Managed values override local configuration." The macOS desktop app doesn't support [otel] in requirements yet, so desktop users still need it in config.toml.
For Codex spend on the Costs page, connect OpenAI Compliance Logs. Tracking Claude Code usage covers the same reporting for Claude Code.
Step 7: Verify the rollout
In the Codex CLI, run /plugins and check that the plugin is installed. Then run any tool call: use one of the role's MCP servers, or ask Codex to run echo hi there. Servers that use OAuth or a user session issuer prompt the person to sign in.
Back in Speakeasy, open Observability > Tool Logs and filter by MCP Server or User. A call to one of the role's MCP servers appears with the member's identity and client, and the Agent filter narrows the log to Codex. For a local tool call such as echo, set the Type filter to include local tools. The Tool Logs reference covers each column.
How do you change Codex MCP server access later?
Access changes go through the same Team Access tab as the first rollout:
- Adding a server. Grant the role Connect access on the new server. Speakeasy adds it to the role's plugins and publishes.
- Removing a server. Remove the role from the server's Team Access. Speakeasy removes the server from the role's plugins unless another role assigned to the same plugin still has access. Tool calls are refused right away, even from clients that still hold the older plugin.
Speakeasy publishes automatically when a plugin or its servers change, batching changes made within a few seconds of each other. ChatGPT and Codex marketplaces sync from GitHub once a day, and Sync now under Admin > Plugins > Marketplaces pulls a change immediately. For a removed server, the sync only decides when it leaves the plugin, since its calls already stopped at removal. Keep the plugin current has the details.
On the OpenAI side, deploying an empty mcp_servers table in requirements stops all MCP usage immediately. Deleting the marketplace in ChatGPT deletes every plugin imported from it, so change access in Speakeasy instead.
Where this setup stops
These limits come with managing Codex MCP servers through device plugins and allowlists.
Codex cloud tasks run off-device. Codex cloud web tasks and GitHub code review emit no device telemetry, so neither the plugin nor the [otel] configuration covers them. The OpenAI Compliance Logs integration brings that usage in, but those imports are post-hoc and can't be blocked in real time.
Installs and calls are separate checks. Speakeasy's plugin assignments don't gate marketplace installs, so the per-role installation policy from step 4 decides who can install each plugin in Codex. Server authorization still decides which tools each person can call, so a member who installs another role's plugin is refused on calls their roles don't allow.
An allowlist checks identity only. However you build it, the allowlist confirms a server's name and identity, not its tools, upstream data, or credentials.
Servers developers add themselves surface in an inventory. Calls that resolve to anything other than a platform-hosted server, including third-party remote URLs and local stdio servers, are flagged as shadow MCP, and that covers Codex's built-in MCP resource tools too. A blocking shadow MCP policy can deny calls to them and give the member a link to request access, and the Codex allowlist in step 5 keeps unapproved servers from starting at all. Discovery depends on sessions reaching the platform, and sessions from an uninstrumented client produce no traffic to scan.
If you're rolling out MCP servers to Codex and want to walk through the allowlist and role plugins for your workspace, talk to our team.