Skip to main content
Back to blog
AI & MCP

How to manage Codex MCP servers for your team

Nolan Sullivan

Nolan Sullivan

Published · 16 min read

How to manage Codex MCP servers for your team

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 --env flags 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 in config.toml holds 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.toml settings 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_servers allowlist, 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_servers is 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 = true with 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.

How approved servers reach Codex, and how calls are checked and loggedThree groups. Deliver: in Speakeasy, grant the role Connect access to the server on its Team Access tab. Speakeasy adds the server to the role's plugin and publishes the marketplace. The ChatGPT workspace imports the marketplace and sets the installation policy per role. Codex receives the plugin. Enforce in Codex, optional, step 5: with the Codex allowlist, plugin-bundled and standalone servers that don't match an entry are disabled. Call: Speakeasy server authorization refuses tool calls the person's roles don't allow, and Tool Logs record the call with the person and client.CODEX MCP ROLLOUTHow approved servers reach Codex, and how calls are checked and loggedDeliverEnforce in Codex (optional)CallSTEP 2 · SPEAKEASYTeam AccessGrant the role Connectaccess to the server.STEP 2 · SPEAKEASYDistributionSpeakeasy adds theserver to the role'splugin and publishesthe marketplace.STEPS 3, 4 · CHATGPTAdmin > PluginsThe ChatGPT workspaceimports the marketplaceand sets the installationpolicy per role.CLIENTCodexReceives the plugin.STEP 5 · REQUIREMENTSCodex allowlistPlugin-bundled and standaloneservers that don't match anentry are disabled.SPEAKEASYServer authorizationRefuses tool calls the person'sroles don't allow.STEP 7 · SPEAKEASYTool LogsRecord the call with the personand client.How approved servers reach Codex, and how calls are checked and loggedThree groups. Deliver: in Speakeasy, grant the role Connect access to the server on its Team Access tab. Speakeasy adds the server to the role's plugin and publishes the marketplace. The ChatGPT workspace imports the marketplace and sets the installation policy per role. Codex receives the plugin. Enforce in Codex, optional, step 5: with the Codex allowlist, plugin-bundled and standalone servers that don't match an entry are disabled. Call: Speakeasy server authorization refuses tool calls the person's roles don't allow, and Tool Logs record the call with the person and client.CODEX MCP ROLLOUTHow approved servers reachCodex, and how calls arechecked and loggedDeliverEnforce in Codex (optional)CallSTEP 2 · SPEAKEASYTeam AccessGrant the role Connect accessto the server.STEP 2 · SPEAKEASYDistributionSpeakeasy adds the server to the role'splugin and publishes the marketplace.STEPS 3, 4 · CHATGPTAdmin > PluginsThe ChatGPT workspace imports themarketplace and sets the installationpolicy per role.CLIENTCodexReceives the plugin.STEP 5 · REQUIREMENTSCodex allowlistPlugin-bundled and standalone serversthat don't match an entry are disabled.SPEAKEASYServer authorizationRefuses tool calls the person's rolesdon't allow.STEP 7 · SPEAKEASYTool LogsRecord the call with the personand client.

Before you start

  • Speakeasy admin. Publishing the marketplace needs the project:write scope and creating an API key needs org: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 the plugins table is present, Codex disables plugin-bundled servers without a matching entry.
  • Allowlist standalone servers. The plugins table covers only plugin-bundled servers, so add a top-level mcp_servers table too. Once it's present, Codex disables any configured server that doesn't match it.
  • Restrict marketplace sources. Set restrict_to_allowed_sources = true under [marketplaces] and add a git source 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.

Frequently asked questions
How do I add an MCP server to Codex?
For one developer, run codex mcp add <server-name> with the server's command, or add a [mcp_servers.<server-name>] table to ~/.codex/config.toml. For a team, publish approved servers in a role plugin to a marketplace the ChatGPT workspace imports. In the Speakeasy AI Control Plane, granting a role Connect access to a server adds it to the role's plugins and publishes the marketplace.
Can admins restrict which MCP servers Codex uses?
Yes. In the Admin Console under Agent security, an mcp_servers allowlist in requirements makes the client enable an MCP server only when both its name and identity match an approved entry. Servers bundled in a plugin are allowlisted separately, under plugins.<plugin>.mcp_servers.<server>. An empty mcp_servers table disables all MCP servers, and overrides apply different settings to specific users, groups, or roles.
Does the Codex MCP allowlist install servers for users?
No. OpenAI's security cookbook says an allowlist entry permits a matching server but does not create the server configuration. A plugin marketplace delivers the configuration. In Speakeasy, each role's plugin carries the servers the role can connect to, and the ChatGPT installation policy decides which workspace roles get it installed automatically or can install it themselves.
How do I see which MCP tools developers call from Codex?
Install Speakeasy's observability plugin through the ChatGPT workspace and turn on Codex's OpenTelemetry export, which ties Codex sessions to individual users. Observability > Tool Logs then shows each call's server, tool, user, client, and status, and the Agent filter narrows the log to Codex.
Does Speakeasy's Codex monitoring cover Codex cloud tasks?
Not through the device plugin or Codex's OpenTelemetry export. Codex cloud web tasks and GitHub code review run off-device and emit no device telemetry. Speakeasy's OpenAI Compliance Logs integration imports that usage, but the imports are post-hoc and can't be blocked in real time.
What happens when someone loses access to an MCP server?
Removing the role from the server's Team Access in Speakeasy removes the server from the role's plugins, unless another role on the same plugin still has access. Tool calls are refused right away, even from clients that still hold the older plugin. ChatGPT and Codex sync the marketplace once a day, or immediately with Sync now.

AI everywhere.

Control here.