Bosphorus

← Knowledge base

Your own keys in OpenBao: Context7 and O'Reilly

An administrator connects Context7 and O'Reilly once; each person keeps their own key in their own OpenBao folder, set from My variables or OpenBao.

ToolsMy variablesOpenBaoSecurityChecked against the product on

Many developers already reach two tool servers straight from their editor: Context7 for current library documentation and O’Reilly for books, videos and courses. Each needs a personal key, so each person’s .mcp.json carries one:

"oreilly": {
  "type": "http",
  "url": "https://api.oreilly.com/api/content-discovery/v1/mcp/",
  "headers": {
    "Authorization": "Bearer ${OREILLY_MCP_TOKEN}"
  }
},
"context7": {
  "type": "http",
  "url": "https://mcp.context7.com/mcp",
  "headers": {
    "CONTEXT7_API_KEY": "${CONTEXT7_API_KEY}"
  }
}

That works for one person on one machine. It does nothing for the chat workspace, for agents or for a colleague, and the key sits in an environment variable or a file. This article moves both servers behind the platform. An administrator connects each one once. Each person keeps their own key in their own OpenBao folder, sets or changes it from the console or from OpenBao, and the key goes out only on their own calls. It is never in a chat, a config file or a shared account.

Everything below was done on a live system on 27 September 2026. The screenshots are real, with names and addresses replaced.

Who does what

Step Who Where
Register the server Administrator Console, /mcp → Register a server
Declare the variable, on that server Administrator Console, /mcp → Variables
Save their own key, then Sync tools Administrator My variables (/vault), then /mcp
Save, check and change their own key Each person My variables, OpenBao web UI or bao CLI

People cannot register servers or declare variables themselves: each of those decides where the platform sends traffic and credentials. What they control is their own key.

Where your key lives

Every person’s values sit in one folder of the kv secrets engine (KV version 2):

kv/
└── users/
    └── ayse.demir@corp.example/
        └── mcp/
            ├── context7    CONTEXT7_API_KEY
            └── oreilly     OREILLY_MCP_TOKEN

Read the path kv/users/<email>/mcp/<server> part by part:

Part What it is What to get right
kv The secrets engine Always kv
users/<email> Your personal vault Your address exactly as your sign-in spells it, including case. bao token lookup shows it as meta.email
mcp The only folder the platform reads Anything you keep elsewhere in your vault is yours alone and never sent anywhere
<server> One secret per tool server The server’s slug, shown in brackets on /mcp, for example oreilly (oreilly)
the key inside One key per declared variable The variable’s name, exactly and in capitals: CONTEXT7_API_KEY, OREILLY_MCP_TOKEN

Two more things about the path:

Part A: the administrator

A1. Start from what your .mcp.json already says

Each entry of the .mcp.json above answers a question on the console’s forms:

In .mcp.json On the console
The entry’s name, oreilly Name. It becomes the server’s slug, which is also the OpenBao secret name. Keep it identical
url URL (streamable HTTP endpoint)
The header’s name The variable’s Header
The header’s value around ${…} The variable’s Template, with ${value} where the key goes
The ${…} name The Variable name people see

The slug is fixed when the server is registered. If the name is already taken, the platform adds -2, and the OpenBao folder follows the slug, so check the brackets on /mcp before you tell people where their key lives.

A2. Register each server

On /mcp → Register a server, enter the name and URL, leave Auth at none (there is no shared key: every person brings their own), and tick require user (signed assertion). Then press Register & sync.

Registering context7 on /mcp: name context7, the Context7 URL, auth none, require user ticked

Context7 answers without a key, so its tools appear at once. O’Reilly refuses anyone without a token, so its first sync fails, and the row says exactly what to do next:

The oreilly row right after registering: status error, mcp http 401 on initialize, with the instruction to declare a per-person variable

That is expected. The next two steps fix it.

A3. Declare the variable, and choose the server first

On /mcp → Variables → Declare a variable, the first field is Server. It decides everything else about this variable:

Declare a variable: Server oreilly (highlighted), variable OREILLY_MCP_TOKEN, delivery header, header Authorization, template Bearer ${value}, required and secret ticked

The rest of the form comes straight from the header line in .mcp.json:

Server Variable Delivery Header Template Required Secret
context7 CONTEXT7_API_KEY header CONTEXT7_API_KEY (blank: the raw value) yes yes
oreilly OREILLY_MCP_TOKEN header Authorization Bearer ${value} yes yes

Write a description for each; people read it on their own page. After Declare, both servers show their variable and where it is delivered:

The Variables tab: context7 delivers CONTEXT7_API_KEY as the raw value, oreilly delivers OREILLY_MCP_TOKEN into Authorization as Bearer ${value}

What the platform enforces for you: people supply values only, never a header or a template; transport headers and the platform’s own headers cannot be targeted; and a required variable that a person has not set stops their call with a link to their page, before anything reaches the tool server.

A4. Save your own key, then Sync tools

A server with no shared key refuses even to list its tools anonymously. Sync tools therefore runs with the pressing administrator’s own value. Save your own O’Reilly token on My variables first (step B1 below), then press Sync tools on the row:

The oreilly row after Sync tools: status ok, one tool, search_oreilly_content

The cached tool list is what your token can see. Every person’s calls still carry their own token.

By default a server is open to all signed-in users of the allowed teams. For a server only some people should reach, set its Access to granted and add them. The GitHub article walks through the same steps for a third service.

Part B: each person

B1. Save your key on My variables

Sign in to the console and open My variables (/vault). A server whose required key you have not saved says so:

My variables before saving: oreilly shows 1 required not set, with an input and a Save button

Paste your key and press Save. The row then shows set, a short fingerprint and in OpenBao. The value is never shown again, not even to you. To change it later, type the new key and press Replace; the fingerprint changes.

The box at the top of the page names your folder and links to it:

My variables: the folder kv/users/ayse.demir@corp.example/mcp/ with a link to open it in OpenBao, and context7 and oreilly both set

B2. Check it in OpenBao

Follow open my folder in OpenBao. Choose method OIDC, leave Role blank, and sign in with the same company account you use for the console. An administrator should also leave the role blank for this: the administrator role is for running the vault, not for personal keys.

The OpenBao sign-in: method OIDC, role blank, Sign in with OIDC Provider

The link opens mcp/ in your folder. There is one secret per server:

The OpenBao folder users/ayse.demir@corp.example/mcp listing context7, envkit, github and oreilly

Open one. It holds one key, named exactly like the variable, with its value masked until you reveal it:

The secret users/ayse.demir@corp.example/mcp/context7: key CONTEXT7_API_KEY, value masked, version 1

B3. Change it in OpenBao

On the secret, press Create new version, replace the value, and Save. Keep the key name exactly as it is, and do not delete the other rows if the secret has several keys: the new version is the whole secret.

Create new version: key CONTEXT7_API_KEY with the value masked, Save and Cancel

There is nothing to save on the console. The platform reads your folder on every call, so the next call uses the new key, and My variables shows the new fingerprint and time:

My variables after the change in OpenBao: a new fingerprint and an updated time

A key typed into OpenBao is checked exactly like one saved on the console: no line breaks, at most 8 KiB, and the variable’s format. A value that fails is refused as unusable rather than sent. A key you add under a name the server does not declare is kept and never sent.

B4. The same from the command line

Point the bao client at your vault and sign in; a browser window completes the company sign-in:

export BAO_ADDR=https://vault.corp.example
bao login -method=oidc
bao token lookup

bao token lookup shows your folder name as meta.email. List your folder, read a secret and see its versions:

bao kv list kv/users/ayse.demir@corp.example/mcp
bao kv get kv/users/ayse.demir@corp.example/mcp/context7
bao kv metadata get kv/users/ayse.demir@corp.example/mcp/context7

To change one key, use patch, and pass the value on standard input so it never lands in your shell history (read -rs does not echo what you paste):

read -rs NEWKEY
printf '%s' "$NEWKEY" | bao kv patch kv/users/ayse.demir@corp.example/mcp/context7 CONTEXT7_API_KEY=-
unset NEWKEY

Do not use bao kv put to change one key. put writes a whole new secret: every key you do not name is dropped. patch changes only the keys you name. This matters for a server with several variables.

What each command answered for a member, run against the live vault:

Command Result
bao token lookup meta.email = your address; policies default and personal
bao kv list …/mcp context7, envkit, github, oreilly
bao kv list kv/users/ 403: nobody may list who has a vault
bao kv get …/mcp/context7 CONTEXT7_API_KEY and its value, version 2
bao kv metadata get …/mcp/context7 versions 1 and 2 with their times
put with one key on a two-key secret the other key was gone
patch with one key on a two-key secret the other key was kept

Use it from your editor

Once both servers are on the platform, your .mcp.json no longer carries anybody’s key. It points at the platform’s relay and sends your personal platform key; the relay adds your Context7 or O’Reilly key from your folder on the way out:

"context7": {
  "type": "http",
  "url": "https://ai.corp.example/api/mcp/context7",
  "headers": {
    "Authorization": "Bearer ${BOSPHORUS_KEY}"
  }
},
"oreilly": {
  "type": "http",
  "url": "https://ai.corp.example/api/mcp/oreilly",
  "headers": {
    "Authorization": "Bearer ${BOSPHORUS_KEY}"
  }
}

Replace ai.corp.example with your platform’s address. The last part of each URL is the server’s slug. The chat workspace, the editor extension and agents reach the same servers the same way, each with the key of whoever is asking. In aimo for VS Code there is nothing to add to a file: once you are signed in it reaches the same servers through the relay, and its Vault view writes your variables into the same folder.

What the platform promises about your key

When something is not right

Situation What to do
This tool needs your own OREILLY_MCP_TOKEN … Save your key on My variables; the message links there.
Sync tools shows mcp http 401 The administrator pressing it has not saved their own key yet (A4).
OpenBao says permission denied on users/ Expected: nobody may list other vaults. Open your folder by its full path, or use the console’s link.
A key you typed in OpenBao is not used Check the secret name is the server’s slug, the key name is the variable’s name in capitals, and the email in the path matches bao token lookup exactly.
My variables shows the value as not usable The value breaks a rule (line break, over 8 KiB, wrong format). Create a new version with a clean value.
You used put and lost other keys Open the previous version in OpenBao, copy the missing values, and create a new version with all keys.
could not be read from the vault just now OpenBao is briefly unreachable. Try again in a minute; if it persists, tell your administrator.
You are leaving Remove your values on My variables, or ask an administrator to delete them.