claude-code - 💡(How to fix) Fix [BUG] `claude mcp get` prints full env values in plaintext (secret leak)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

claude mcp get <name> prints the full Environment: block verbatim — including secret values like database DSNs, API tokens, or any other credentials passed via --env KEY=VALUE when the server was registered. There is no masking and no opt-in for plaintext display. Running it for routine diagnostic purposes (e.g. "is this server still configured?") leaks the secret to wherever stdout is captured: terminal scrollback, screen-shares, log files, agent chat transcripts, paste-board buffers.

This forced a credential rotation in our environment today when a routine claude mcp get postgres-bdcscope-readonly echoed the full Postgres DSN (user + password + host + database) into an agent transcript.

Root Cause

  1. Agent / automation contexts: any Claude Code agent that runs mcp get for diagnostic purposes will write the secret into its conversation transcript, which is often persisted indefinitely (Anthropic logs, local JSONL, harness storage).
  2. Screen sharing / pair programming: running mcp get to confirm a server is configured is exactly the kind of "show, don't tell" moment where the operator forgets the output contains secrets.
  3. Log capture: terminal multiplexers (tmux, screen), shell history with timestamps, and CI loggers all routinely capture stdout. A single mcp get poisons all of them.
  4. No warning, no opt-in: mcp list correctly redacts (shows only Command: line, no env). mcp get does the opposite without warning. The asymmetry surprises operators.

Fix Action

Fix / Workaround

Workaround until this lands

Code Example

claude mcp add my-server --scope local \
  --env DATABASE_URI=postgresql://alice:s3cret@db.example.com/prod \
  -- some-mcp-binary --flag

claude mcp get my-server

---

my-server:
  Scope: Local config (private to you in this project)
  Status:Connected
  Type: stdio
  Command: some-mcp-binary
  Args: --flag
  Environment:
    DATABASE_URI=postgresql://alice:s3cret@db.example.com/prod

---

Environment:
  DATABASE_URI=<redacted, 53 chars> (use --reveal-env to show)
  LOG_LEVEL=info
  PORT=3000
RAW_BUFFERClick to expand / collapse

Summary

claude mcp get <name> prints the full Environment: block verbatim — including secret values like database DSNs, API tokens, or any other credentials passed via --env KEY=VALUE when the server was registered. There is no masking and no opt-in for plaintext display. Running it for routine diagnostic purposes (e.g. "is this server still configured?") leaks the secret to wherever stdout is captured: terminal scrollback, screen-shares, log files, agent chat transcripts, paste-board buffers.

This forced a credential rotation in our environment today when a routine claude mcp get postgres-bdcscope-readonly echoed the full Postgres DSN (user + password + host + database) into an agent transcript.

Reproduction

claude mcp add my-server --scope local \
  --env DATABASE_URI=postgresql://alice:[email protected]/prod \
  -- some-mcp-binary --flag

claude mcp get my-server

Output includes:

my-server:
  Scope: Local config (private to you in this project)
  Status: ✓ Connected
  Type: stdio
  Command: some-mcp-binary
  Args: --flag
  Environment:
    DATABASE_URI=postgresql://alice:[email protected]/prod

The password is in plaintext. No flag was passed to opt into seeing it.

Why this matters

  1. Agent / automation contexts: any Claude Code agent that runs mcp get for diagnostic purposes will write the secret into its conversation transcript, which is often persisted indefinitely (Anthropic logs, local JSONL, harness storage).
  2. Screen sharing / pair programming: running mcp get to confirm a server is configured is exactly the kind of "show, don't tell" moment where the operator forgets the output contains secrets.
  3. Log capture: terminal multiplexers (tmux, screen), shell history with timestamps, and CI loggers all routinely capture stdout. A single mcp get poisons all of them.
  4. No warning, no opt-in: mcp list correctly redacts (shows only Command: line, no env). mcp get does the opposite without warning. The asymmetry surprises operators.

Proposed fix

Mask by default; require an explicit flag to reveal.

Suggested behavior for claude mcp get <name>:

Environment:
  DATABASE_URI=<redacted, 53 chars> (use --reveal-env to show)
  LOG_LEVEL=info
  PORT=3000

Heuristic for "looks like a secret" (any one of):

  • Key name matches /(_TOKEN|_KEY|_SECRET|_PASSWORD|_DSN|_URI|_URL|API_)/i
  • Value matches a known credential shape: postgres://, postgresql://, mysql://, JWT (eyJ...), 32+ char hex, 24+ char base64, etc.
  • Value length > 24 chars and not in a small whitelist of obviously-non-secret tokens (http://, https://localhost, etc.)

Add --reveal-env (or --show-secrets) to opt back into the current behavior. Match the convention gh auth status already uses (Token: gho_*****...).

Workaround until this lands

For our team, we now require any MCP re-registration to go through a Python wrapper that scrubs DSN-shaped content from subprocess.run captured output before printing. The claude mcp get command is effectively banned from agent and screen-share contexts. Both are friction we'd rather not carry.

Environment

  • claude-code version: 2.x (latest as of 2026-05-30)
  • OS: Windows 11
  • Stdio MCP server registered with --env DATABASE_URI=postgresql://...

Happy to provide a PR for the masking heuristic if you'd like — the logic is straightforward and could ship behind a feature flag for a release before becoming default.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix [BUG] `claude mcp get` prints full env values in plaintext (secret leak)