# Shager in OpenAI Codex: config.toml, bearer_token_env_var and a Tool Allowlist That Keeps Drafts as Drafts

_2026-08-20 · Set up Shager's remote MCP server in Codex CLI via config.toml or codex mcp add, read the key from an env var, restrict tools, and create a first draft._

To connect Shager to OpenAI's Codex CLI, add an `[mcp_servers.shager]` table to `~/.codex/config.toml` with `url = "https://app.shager.ai/api/mcp"` and `bearer_token_env_var = "SHAGER_API_KEY"`, then export your `shgr_live_` key in that variable. Codex speaks streamable HTTP natively and sends the key as a bearer token, so no bridge or local process is needed. You can also do it in one line with `codex mcp add shager --url ... --bearer-token-env-var SHAGER_API_KEY`.

The rest of this guide is about doing it in a way you won't regret: keeping the key out of the file, limiting which Shager tools Codex can call, and picking a first task that proves the wiring.

## What does Codex support for remote MCP servers?

OpenAI's [Codex MCP documentation](https://developers.openai.com/codex/mcp) describes streamable HTTP servers configured with a `url`, plus three ways to authenticate with headers. The [configuration reference](https://developers.openai.com/codex/config-reference) defines them:

| Key | What it does |
|---|---|
| `bearer_token_env_var` | Name of an environment variable whose value is sent as the bearer token |
| `http_headers` | Static headers included with each request |
| `env_http_headers` | Headers whose values are read from environment variables |

Shager expects `Authorization: Bearer shgr_live_...`, which is exactly what `bearer_token_env_var` produces. That is the option to use.

## Option A: edit config.toml

Open `~/.codex/config.toml` and add:

```toml
[mcp_servers.shager]
url = "https://app.shager.ai/api/mcp"
bearer_token_env_var = "SHAGER_API_KEY"
```

Then put the key in your shell profile, not in the TOML:

```bash
export SHAGER_API_KEY="shgr_live_your_key_here"
```

Note that the config holds the variable's name, not the key itself. That means you can commit or share the snippet freely, and each teammate supplies their own key. Separate keys per person pay off later, because Shager's audit log at https://app.shager.ai/dashboard/agents records every call against the key that made it.

## Option B: codex mcp add

The CLI writes the same table for you. The Codex source for `codex mcp add` defines `--url` for streamable HTTP servers and a `--bearer-token-env-var` flag that requires it ([mcp_cmd.rs on GitHub](https://github.com/openai/codex/blob/main/codex-rs/cli/src/mcp_cmd.rs)):

```bash
codex mcp add shager \
  --url https://app.shager.ai/api/mcp \
  --bearer-token-env-var SHAGER_API_KEY
```

If your installed version differs, `codex mcp add --help` is the source of truth.

Check the result:

```bash
codex mcp list
```

Inside the Codex TUI, `/mcp` shows active servers and their tools.

## Should you use http_headers instead?

You can, but you shouldn't. `http_headers = { "Authorization" = "Bearer shgr_live_..." }` works, and it puts a live credential in a plain text file that tends to get copied into dotfile repos. If you need a header other than the bearer token, `env_http_headers` maps a header name to an environment variable name:

```toml
[mcp_servers.shager]
url = "https://app.shager.ai/api/mcp"
env_http_headers = { "Authorization" = "SHAGER_AUTH_HEADER" }
```

With that form, the variable must contain the full value, including the scheme: `export SHAGER_AUTH_HEADER="Bearer shgr_live_..."`. For Shager, `bearer_token_env_var` is simpler and does the same thing.

## How do you limit what Codex can do in Shager?

This is the part most setup guides skip. Codex lets you filter a server's tools with `enabled_tools` (an allow list) and `disabled_tools` (a deny list applied after it), both documented in the configuration reference. Combine that with Shager's key scopes and you get two layers that fail closed.

A drafting profile that can read everything and create drafts, but cannot schedule, cancel or create connect links:

```toml
[mcp_servers.shager]
url = "https://app.shager.ai/api/mcp"
bearer_token_env_var = "SHAGER_API_KEY"
enabled_tools = [
  "whoami",
  "list_workspaces",
  "list_channels",
  "list_groups",
  "upload_media_from_url",
  "create_post",
  "get_post",
  "list_posts",
  "get_analytics",
]
tool_timeout_sec = 120
```

`create_post` stays in the list because without `schedule_at` it only saves a draft. If the key also lacks the `publish` scope, Shager rejects any `create_post` that includes `schedule_at` with a 403, so even a creative model can't sneak a scheduled post through.

The `tool_timeout_sec` bump is there because `upload_media_from_url` downloads the file server side, and a large vertical video can take longer than the default 60 seconds the reference lists.

## A first task worth running

Start with a prompt that touches several tools and leaves only a draft behind:

```text
Use the shager MCP server.
1. whoami, then list_workspaces.
2. In workspace "Lakeside Realty", list_channels and list_groups.
3. upload_media_from_url https://example.com/media/open-house.jpg
4. create_post as a draft to group "All agents" with a different caption per
   channel (per_channel), mentioning each agent's neighborhood from the channel
   name. cta_url https://lakesiderealty.example/open-house, campaign
   "open-house-oct", first_comment "Details and RSVP: " followed by the link.
5. get_post and print a table of channel, network, format and state.
```

What you should see: a post in `DRAFT` status with one destination per account, each with its format resolved for that network. In Shager, every account gets its own short link and UTM tags for the `cta_url`, with `utm_content` naming the account, which is what makes per-account attribution work later. The details are in [per-account lead attribution](/en/blog/utm-per-account-lead-attribution).

## Can Codex run this without a human at the keyboard?

Codex has a non-interactive `codex exec` mode for scripts and CI. How MCP tool approvals behave in a headless run has changed between releases, so test a dry run on your installed version before you put it on a timer. For a job that must run unattended every week, many teams skip the chat layer and call Shager's REST API from a short script, which has no approval prompts to get stuck on. Whichever you choose, give the job its own key, keep the tool allowlist tight, and decide deliberately whether that key carries `publish`. A routine built around those choices is laid out in [the weekly distribution routine](/en/blog/skill-weekly-distribution-routine).

## Troubleshooting

| What you see | Cause | Fix |
|---|---|---|
| 401 `unauthorized` | Variable not exported in the shell that launched Codex | `echo $SHAGER_API_KEY` in the same terminal, then restart Codex |
| Tools missing from `/mcp` | Name not in `enabled_tools`, or listed in `disabled_tools` | Check the spelling against the tool list on [/en/agents](/en/agents) |
| 403 `sandbox_unclaimed` | Key came from agent self-signup and no human has claimed it | Send the `claim_url` to a human |
| 403 `forbidden` on scheduling | Key lacks `publish` | Expected for a drafting key |
| 429 `rate_limited` | Over 120 requests per minute per key | Use groups and one `create_post` instead of one call per account |

## FAQ

### Does Codex need OAuth to talk to Shager?

No. Codex supports bearer tokens from an environment variable, which is how Shager authenticates today. Shager's OAuth for MCP is coming, and Codex also supports OAuth servers, but you don't need to wait for it.

### Is the Shager setup different in the Codex IDE extension?

OpenAI's MCP docs say the ChatGPT desktop app, Codex CLI and IDE extension share this configuration, so the same `~/.codex/config.toml` table serves all of them. Make sure the environment variable is visible to the editor process, which on macOS can mean launching the editor from a terminal.

### Can I point Codex at the REST API instead of MCP?

Yes, if you're writing code rather than chatting. The [OpenAPI document](https://app.shager.ai/api/v1/openapi.json) describes the same operations as the MCP tools, with the same scopes and limits.

## Next step

With Codex connected, get comfortable with the operations themselves before automating anything. The [REST API quickstart](/en/blog/shager-rest-api-quickstart) walks the full sequence from workspace to tracked post with curl and Python, which also helps you read what Codex is doing when it calls the MCP tools.

---
Source: https://shager.ai/en/blog/connect-shager-to-codex
