⚒ toolshedadd MCP tools to Claude Code & Codex v0.2.1

SecretsTokens in your keychain, not in config files

When a tool needs a secret, such as an API token, toolshed asks for it when you install the tool, at a hidden prompt, and keeps it in your OS keyring: the macOS Keychain, or the Secret Service on Linux. It’s stored under service toolshed, account <id>/<KEY>.

Command servers

A server that gets its token from an environment variable is registered with Claude Code and Codex as a wrapper, not as the server itself:

toolshed exec jira --secret JIRA_TOKEN=jira -- jira-mcp --site acme

That line is all the client’s config contains. When the client starts the server, toolshed exec reads the secrets from the keyring, adds them to the environment, and then replaces itself with the real server (the exec system call). The client talks to the server directly, with nothing in between. toolshed exec doesn’t read your registry: everything it needs is in its arguments, so an installed tool keeps working if you move the registry.

Remote servers with a token

A remote server that wants an API token gets it in a header:

toolshed add acme --url https://mcp.acme.com/mcp \
  --header 'Authorization=Bearer ${ACME_TOKEN}' --secret ACME_TOKEN

In the TUI, answer “yes” to “Does it need an API token?”. At install you enter the token, and it goes to your keyring. Claude Code (headersHelper) and Codex (http_headers_helper) are both registered with a headers helper, toolshed headers acme …, which they run when they connect: it reads the token from the keyring and prints the headers. The token is never in their config files.

A literal token in a header (--header 'Authorization=Bearer ghp_…') is refused, because it would be stored in your registry in plain text. The same goes for your agent’s add_server.

Replacing a secret

toolshed secret set jira

Installed tools read the keyring each time they start, so a rotated token needs nothing else. The value is typed at a hidden prompt, or piped in (pbpaste | toolshed secret set jira); it’s never an argument, where it would end up in your shell history. Tools that share a secret (share: in the registry) all get the new value.

Without a keyring

On CI, SSH-only machines, or with TOOLSHED_NO_KEYRING=1, there’s no keyring, and secrets go into the client’s config as plain values (Claude Code env / headers, Codex env / http_headers). toolshed refuses to do that for a --project install, because a project’s config is meant to be committed.

What it protects against

The keyring keeps tokens out of dotfiles, backups, screen shares and accidental commits. It doesn’t isolate them from other programs running as you: on macOS, toolshed stores them through the security tool, so any process of yours can read them back.

docs/secrets.md on GitHub ↗