Skip to main content
Glama
secret-paste

secret-paste

secret-paste

An MCP server that lets an agent request an API key or other secret from you without you pasting it into the chat. The value never passes through the conversation, a tool argument, or a tool result. "pbcopy for agents."

The agent calls request_secret. A native password dialog pops up (pinentry, zenity, kdialog, or a macOS dialog), you type the value, and it goes straight to .env, your OS keychain, or 1Password. No browser tab, no "save this password?" nag. If no dialog tool is available, a local browser page is used instead. The agent only ever sees { name, target, stored }.

This keeps the secret out of the request path, not out of the agent's reach. Once stored, an agent with shell access can still read it (cat .env, secret-tool lookup, op item get), and anything it reads lands in the transcript. Pair this with permission rules that deny reading .env or running those commands if that matters to you.

Install

cd /path/to/secret-paste
npm install && npm run build
claude mcp add --scope user secret-paste -- node /path/to/secret-paste/dist/server.js

Restart Claude Code (or run /mcp) and confirm secret-paste is connected.

Related MCP server: keyward

Tool

request_secret({ name, target?, description? })

field

notes

name

required, must match ^[A-Z_][A-Z0-9_]*$

target

env (default), keychain, or op

description

optional, shown on the page

Result on success: { "name": "...", "target": "...", "stored": true, "path"?: "...", "readHint": "...", "via": "<backend>" }. Result otherwise: { "stored": false, "reason": "cancelled" | "timeout" | "<error>", "via": "<backend>" }.

via is one of pinentry, pinentry-mac, zenity, kdialog, osascript, elicitation (browser page opened through the client), or browser (browser page opened with xdg-open / open).

The value, its length, a prefix, or a hash is never returned, logged, or echoed.

Targets

  • env: upserts NAME=value into .env in the server's working directory (the directory Claude Code was started in). Other lines are preserved, an existing line for that name is replaced, the file is created with mode 0600 if missing, and .env is appended to .gitignore when the directory is a git repo. Values are written unquoted when possible, otherwise wrapped in ', `, or " (whichever the value doesn't contain) so dotenv and Node's process.loadEnvFile read them back verbatim. Values that can't be quoted losslessly are rejected with a hint to use keychain or op.

  • keychain: macOS security add-generic-password (fed over stdin via security -i, so the value never appears in ps), or Linux secret-tool store (requires libsecret-tools).

  • op: op item create with a JSON item template on stdin (1Password CLI), saved to your default vault. Read it back with op item get NAME --fields label=password --reveal.

How it works

Native dialog (default)

Backends are tried in order until one is available:

platform

order

Linux

pinentry, zenity, kdialog, browser

macOS

pinentry-mac, pinentry, osascript, browser

Windows

browser

  • pinentry is GnuPG's passphrase prompter and the preferred backend. It holds the value in locked memory, draws a native dialog (GNOME/GCR, Qt, GTK, or macOS depending on the installed flavour), and enforces the timeout itself. The server speaks the Assuan protocol to it over stdin/stdout and decodes the D response at the byte level. Terminal-only flavours (curses, tty) are skipped because the server has no terminal to give them. SETKEYINFO is deliberately not sent, so pinentry never offers to cache the value in your keyring.

  • zenity --password and kdialog --password print the value to stdout, which the server reads as bytes and zeroes after storing.

  • osascript runs a display dialog ... with hidden answer AppleScript.

Set SECRET_PASTE_PROMPT to override the order, e.g. zenity,browser or browser to force the old behaviour:

claude mcp add --scope user -e SECRET_PASTE_PROMPT=browser secret-paste -- node /path/to/secret-paste/dist/server.js

Dialogs are spawned detached from the server's process group and killed on timeout or when the tool call is aborted.

Browser fallback

  1. A one-shot HTTP server starts on 127.0.0.1 on a random port with a random nonce in the path. Requests with the wrong nonce, Host, or Origin are rejected.

  2. The URL is handed to Claude Code via MCP URL-mode elicitation, which shows a native "open this link?" prompt. If the client doesn't support that, the server falls back to xdg-open / open.

  3. The page is static HTML with no JavaScript and Cache-Control: no-store.

  4. On submit, the value is parsed at the byte level into a Buffer, written to the target, then zeroed. It is never held as a JavaScript string.

  5. The server shuts down after one submit or cancel, or after 5 minutes.

The tool is tagged _meta["anthropic/requiresUserInteraction"] = true, so Claude Code prompts for permission on every call, even in auto-accept modes.

How to use it (for Claude)

When you need a credential, call request_secret({ name: "SERVICE_API_KEY" }) and then reference it as process.env.SERVICE_API_KEY (or the readHint in the result). Never ask the user to paste a secret into chat.

Development

npm test        # unit tests: .env upsert, form decoding, dialog backends via fake binaries (node --test)
npm run build   # tsc -> dist/

Available Tools

1 tool
request_secretRequest a secret from the userA

Ask the user for an API key or other secret via a native password dialog (pinentry, zenity, kdialog, or a macOS dialog), falling back to a local browser page. The value is stored directly to the chosen target (.env in the working directory, the OS keychain, or 1Password) and never enters the conversation. Afterwards, reference it indirectly (e.g. process.env.NAME); never ask the user to paste secrets in chat.

Inputs: name (required), target, description.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 1 tool

    Disambiguation5/5

    There is only one tool, so there is no possibility of misselection or overlap. Its purpose (securely obtain and store a secret without exposing it in chat) is unmistakable.

    Naming Consistency5/5

    The single name request_secret follows a clear verb_noun convention and is self-descriptive. With one tool there is nothing to be inconsistent with.

    Tool Count3/5

    The server is narrowly scoped to secret ingestion, so one tool is defensible, but it sits at the thin end of the range. A secret-management surface usually warrants at least a companion tool for checking, rotating, or removing stored secrets.

    Completeness3/5

    Writing a secret to .env, keychain, or 1Password is covered, but the lifecycle is a dead end: there is no way to verify a secret already exists, rotate it, or delete it. Agents must guess or re-prompt the user, which risks redundant dialogs and stale credentials.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables secure credential storage for AI agents by encrypting secrets and providing agent-invisible references, ensuring sensitive data never leaks to the model.
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI agents to securely use API keys by storing them in an encrypted vault and injecting them on demand with user approval, without exposing the key values to the model.
      3
      MIT
    • A
      license
      C
      quality
      C
      maintenance
      Enables AI agents to securely store and manage encrypted secrets locally while using them indirectly through environment-variable injection or file writes, so plaintext values never enter the agent's context.
      8
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      Lets an AI agent request API keys and passwords from a human through an end-to-end encrypted one-time link and pass them to exactly one command or file, without the value ever entering the agent's context. Can also send secrets as self-destructing links.
      3
      AGPL 3.0