# Using multiple TRMNL MCP API keys in a single plugin repo

https://blog.cynexia.com/using-multiple-trmnl-mcp-api-keys-in-a-single-plugin-repo

Author: [Rob Aleck](https://blog.cynexia.com/pages/about) · https://github.com/mnbf9rca · https://www.linkedin.com/in/robertaleck/ · https://family-foqos.app/

Published: 2026-09-08
Updated: 2026-10-01
Categories: How-to


[TRMNL](<https://trmnl.com/>) is an awesome open-source ePaper display that lets users show almost anything they want. Launched on Kickstarter, it’s now got thousands of plugins and users. I’ve published a few plugins, including a [realtime TfL bus stop arrival time board](<https://trmnl.com/recipes/234101>).

A few weeks ago, TRMNL [added an MCP server](<https://help.trmnl.com/en/articles/14130438-ai-agent#h_1f68fdf82e>). This lets you use a local coding agent to do most of the grunt work.

## Install the MCP server through .mcp.json

Using Claude Code, i created a simple `.mcp.json` file which references the API key by environment variable. Place this in the root of your repo. As it contains no secrets, this is safe to commit:

```json
{
  "mcpServers": {
    "trmnl": {
      "type": "http",
      "url": "https://trmnl.com/mcp?api_key=${TRMNL_MCP_API_KEY}"
    }
  }
}
```

I previously wrote about [how to inject the environment variable at launch time so that Claude can access the MCP server](<https://blog.cynexia.com/running-claude-code-under-op-run-breaks-resume>).

## Each plugin gets its own MCP API key

The TRMNL MCP server is designed so that each plugin gets its own MCP API key, which i [store in 1Password](<https://blog.cynexia.com/updated-using-1password-and-direnv-to-store-developer-secrets>). But i store my plugins in a single “monorepo” - so my standard approach of just injecting at runtime wouldnt work because a single `.env.tpl` at the root of the repo can only hold a single MCP API key, so i would have to manually edit that file every time i wanted to switch plugin.

The best approach seemed to be to store each MCP API key in a field in a single 1Password entry, and dynamically load the correct MCP API key for each claude session, but i was quickly forgetting the exact magic incantation (command).

## Store a .env.tpl in each plugin folder, and reference that

Each plugin directory gets its own `.env.tpl` which maps variable names to `op://` references, but as there are no secrets it is safe to commit it to git. Each file includes that specific plugin's MCP key under the same variable name, and i can add whatever other plugin-specific secrets i need. For example:

```
# national_rail_departures/.env.tpl
TRMNL_MCP_API_KEY=op://TRMNL/trmnl/mcp_api_key_national_rail_departures
RAILDATA_API_KEY=op://TRMNL/raildata/1010-live-departure-board_consumer_key
```

and

```she
# simple_tube_status/.env.tpl
TRMNL_MCP_API_KEY=op://TRMNL/trmnl/mcp_api_key_simple_tfl_status
```

.`mcp.json` at the repo root reads `${TRMNL_MCP_API_KEY}` from the environment, and that is injected through whichever template we load.

Now we can launch Claude with a single command:

```bash
op run --no-masking --env-file="<plugin_folder>/.env.tpl" -- claude
```

## Create a shortcut which is easy to remember

That’ll work, but like i said before, it’s hard to remember, so I added a simple shell script which takes the folder name, loads the `.env.tpl` file from that folder, and injects the resolved secrets to the Claude process as environment variables. The script is saved as `bin/op_claude` in the project folder.

```
#!/bin/sh
# Usage: op_claude <plugin_dir> [claude args...]
cd "$(dirname "$0")/.." || exit 1
plugin="$1"
if [ ! -f "$plugin/.env.tpl" ]; then
  echo "usage: op_claude <plugin_dir> [claude args...]  (no $plugin/.env.tpl found)" >&2
  exit 2
fi
shift
exec op run --no-masking --env-file="$plugin/.env.tpl" -- claude "$@"
```

I also added a single line to my `.envrc` to add the `bin` folder to the current path, but only when we’re in the repo folder:

```
PATH_add bin
```

## Launch with a simple command

You can now just type `op_claude` to launch e.g.

- `claude` launches Claude like normal, no API keys, no secrets. The MCP server fails to load.
- `op_claude`  tells you how to use the tool
- `op_claude national_rail_departures` launches Claude and injects `.env.tpl` file from the `national_rail_departures` folder
- `op_claude simple_tube_status --resume <session-id>` launches Claude, injects `simple_tube_status/.env.tpl`, and resumes session `<session-id>`.

Each session sees exactly the correct MCP API key with no manual editing required.

