anthropics / anthropics/claude-code
claude mcp get/list print configured MCP secrets (headers, env vars) in cleartext with no masking
- Dominant language
- Python
- Stars
- 145k
- Forks
- 23.1k
- PR merge metrics
- PR metrics pending
Description
## `claude mcp get`/`list` print configured MCP secrets (headers, env vars) in cleartext with no masking
**Environment**
- Claude Code 2.1.233 (CLI)
- macOS (Darwin 25.5.0)
**Summary**
`claude mcp get ` prints the full configured value of any custom HTTP header or
stdio environment variable set on an MCP server, in cleartext, with no masking. This
includes values that are self-evidently credentials (API keys, tokens) based on the
header/variable name (`x-api-key`, `Authorization`, `*_KEY`, `*_TOKEN`, etc.).
Compare to conventions in other CLI tools that manage credentials in their config/status
output (`gh auth status`, `aws configure list`, `stripe config`) — these mask secret
values by default (e.g. show only a trailing few characters) and require an explicit
flag to reveal the full value.
**Impact**
Any tool, script, screen share, terminal capture, or AI agent session that reads this
command's output gets the live credential. If that output is ever included in another
AI model's context (e.g., pasted for debugging, or read by an agent with terminal
access), the credential propagates the same way any other captured secret would —
with no indication to the user that a masked-by-default field was actually disclosed.
**Steps to reproduce**
```
export TEST_KEY="dummySecretValue999"
claude mcp add --transport http --scope local repro-http https://example.com/mcp \
-H "x-test-key: $TEST_KEY"
claude mcp get repro-http
# Headers: block shows "x-test-key: dummySecretValue999" in full
claude mcp remove repro-http --scope local
claude mcp add --transport stdio --scope local repro-stdio \
-e TEST_SECRET_ENV=dummyStdioSecret777 -- echo hello
claude mcp get repro-stdio
# Environment: block shows "TEST_SECRET_ENV=dummyStdioSecret777" in full
claude mcp remove repro-stdio --scope local
```
Confirmed identical behavior regardless of URL scheme (http vs https) — this is a local
config-echo issue, not a transport-security issue.
**Also noted while investigating:** `-H` header values do not support `${VAR}`-style
environment variable interpolation — a header set to `${SOME_VAR}` is stored and would
be sent literally as the string `${SOME_VAR}`, not resolved. This means there's
currently no supported way to keep a static secret for an HTTP-transport server's
header out of the on-disk config file at all (unlike stdio's `-e`, which at least
keeps the value nominally "in the environment" conceptually, even though `mcp get`
discloses it the same way).
**Suggested fix**
- Mask secret-shaped values in `claude mcp get`/`list` output by default (e.g., last 4
characters only), with an explicit `--reveal`/`--unmask` flag for when a user
actually needs to see the full value.
- Consider supporting `${VAR}` interpolation for HTTP headers so a value can be kept out
of the on-disk config entirely, matching stdio's `-e` model — and if unsupported,
fail loudly rather than silently sending the literal placeholder string as the header
value.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reproducing the disclosure with `claude mcp get` and `claude mcp list` using the HTTP header and stdio environment examples in the issue. Trace the CLI entry points that format MCP server configuration output. Done means secret-shaped headers and environment values are masked by default, with an explicitly documented reveal path, and tests cover both commands and transports.
Written by the indexing model from the issue text.
Assessment
- Domain
- cli, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100