Skip to main content
Glama

meatproxy

A coding agent sometimes needs something only you have: a token, a sudo password, your corrections to a text it wrote. meatproxy is an MCP server that asks you for it in a window on your own screen. A secret goes from that window straight to the one command that needs it, and the agent never sees it. Text you write or fix goes back to the agent.

Русская версия

The agent asks for a GitHub token; a tmux popup shows the command that will receive it

Why "meat proxy"

The term comes from meatproxy.me: a person who only relays text between an AI and the world. When an agent hits a password prompt, you become its meat proxy. You copy the token into the chat, type the sudo password, retype the commit message. The token stays in the transcript and in the provider's logs, and the command it unlocked went by in a scroll of tool calls you half read.

meatproxy_mcp gives the meat proxy a bit more control. Every request opens a window that names who asked, the exact command, its directory and how the value will reach it. You answer there or close the window. The value goes to the command's standard input or to one environment variable, and the agent gets the exit code and the output with the value replaced by [secret]. Nothing is stored: the next call asks again.

Related MCP server: Interactive MCP

What you can use it for

An API key or a token

The agent calls run_with_secret:

{"purpose": "log gh in to github.com", "argv": ["gh", "auth", "login", "--with-token"], "via": "stdin"}

A tmux popup opens over your terminal with the request under an empty first line. You paste the token there and write the file (:wq).

The same popup with a token pasted on the first line

The agent gets back {"status": "ran", "exit_code": 0, "timed_out": false, "stdout": "...", "stderr": "..."}. For a program that reads its key from the environment, the agent passes "via": "env", "env_name": "NODE_AUTH_TOKEN". Outside tmux the same request is a GTK dialog with hidden input:

zenity dialog with hidden input for an npm token

Text in your own editor

Typing a paragraph into a chat box is slow, and the agent's drafts need editing. ask_user opens the draft in your $EDITOR (nvim, helix, micro, anything). What you leave above the marker line goes back to the agent. Use it for a letter, a PR description, a list of hosts, a config the agent should follow.

A reply draft open in nvim inside a tmux popup

ask_user_async returns at once with a reply_id, so the agent can keep working while you write; read_reply collects the text later. Without tmux the draft opens in a GTK text window:

zenity text window with the same draft

Commit messages

A git commit-msg hook can hand the agent's message to you before the commit happens. It opens in the same popup with the staged files listed under it.

The agent's commit message open for review, with the diff stat below

You do

The commit

edit if needed, :wq

goes ahead with your text

:cq, or delete the text and :wq

is aborted; the agent is told to ask you what to change

nothing for 100 s

goes ahead with the agent's text

examples/git-hooks/commit-msg is the hook this setup runs. It acts only when CLAUDECODE=1 (Claude Code sets it for the commands it runs) or HERMES_AGENT=true, so your own commits are left alone. Install it as a global hook:

mkdir -p ~/.config/git/hooks
cp examples/git-hooks/commit-msg ~/.config/git/hooks/
git config --global core.hooksPath ~/.config/git/hooks

core.hooksPath replaces each repository's .git/hooks. The example ends by calling the repository's own commit-msg hook. Other hooks in .git/hooks (pre-commit, pre-push) stop running unless you put a stub with the same last lines next to it for each one. A repository that sets its own core.hooksPath, as husky 5 and later and lefthook do, never runs the global hook. The core of the hook:

meatproxy-edit "$msg" --purpose "commit message for $(basename "$top")" --caller agent \
	--note-file "$stat" --file-name COMMIT_EDITMSG --wait "$wait_seconds"
case $? in
0) ;;        # written back: commit with the user's text
1) exit 1 ;; # :cq or emptied: abort the commit
*) ;;        # 5 timed out, 2 no window: commit the message as written
esac

touch ~/.local/state/commit-review-off turns the review off; COMMIT_REVIEW_WAIT changes the 100 seconds.

sudo, here and over ssh

run_with_sudo(argv, server) runs one command under sudo on this machine or on a host from ~/.ssh/config or an ssh-manager list. The window names the host, the login and the target user. meatproxy feeds the password to sudo -S itself, so it never appears in an argument list or on the remote command line.

Password window for sudo on a remote host over ssh

meatproxy-askpass draws the same window for plain sudo -A, from your shell or the agent's. It reads the calling sudo from /proc and marks commands that are hard to undo:

export SUDO_ASKPASS=/usr/local/bin/meatproxy-askpass
sudo -A systemctl stop nginx

sudo -A asking through meatproxy-askpass, with a warning for a destructive command

It refuses to start unless its parent is sudo. Otherwise an agent could run it directly and read the password from its output.

Tools

Tool

Window says

What comes back to the agent

run_with_secret(purpose, argv, via)

SECRET: the value goes to the stdin or to one variable of the command shown, and is not shown to the agent

exit code, stdout, stderr; the value replaced by [secret]

run_with_sudo(argv, server)

SECRET: sudo reads the password to run the command shown, here or on the named host over ssh

exit code, stdout, stderr; the password replaced by [secret]

ask_user(purpose, draft)

SHARED: what you leave in the window is sent to the agent

your text

ask_user_async(purpose, draft)

the same as ask_user

a reply_id at once

read_reply(reply_id, wait_s)

your text, or pending

One call opens one window and runs one command.

Input methods

Tried in the order of backends in the config; the first that can open a window is used.

Method

When

Window

exec

you configured a program

yours: one JSON line in, one out

tmux

the agent runs inside tmux

popup over the attached client, or a tmux window

zenity

a display and zenity

hidden-input dialog, or an editable text window

terminal

a display, no tmux

a terminal with a hidden prompt or your editor

The tmux and terminal windows open editor from the config, or $VISUAL, then $EDITOR, then nvim. vim, nvim, emacs, micro, nano, helix and kak start with flags that keep the value out of swap and history files. Adding a method, including one for Windows, is described in the backend guide.

Only vim and nvim can quit with an error (:cq). In any other editor, such as nano, quitting without saving sends the text as it was. To refuse there, delete the text, save and quit. A secret then is not sent, and a draft or a commit message is cancelled.

Install

You need Linux and Python 3.12 or newer. To draw the window, you also need at least one of these: tmux 3.3 or newer, zenity, or a terminal emulator in a graphical session. The terminal is xdg-terminal-exec by default; set terminal in the config to use another one.

git clone https://github.com/SilentAutomaton/meatproxy_mcp.git meatproxy
cd meatproxy
python3 -m venv .venv && .venv/bin/pip install -e .
mkdir -p ~/.config/meatproxy
cp config.example.toml ~/.config/meatproxy/config.toml   # optional

Register it with your MCP client as a stdio server. For Claude Code, from the same directory:

claude mcp add --scope user meatproxy -- "$PWD/.venv/bin/meatproxy-mcp"

claude mcp list should show meatproxy as connected. To check the window, start a new session and ask the agent to call ask_user.

The askpass helper and the editor for hooks are two launchers in bin/. They run on the system python3, which must also be 3.12 or newer, and need nothing from the venv. meatproxy-askpass reads /proc, so it works only on Linux.

sudo ln -s "$PWD/bin/meatproxy-askpass" "$PWD/bin/meatproxy-edit" /usr/local/bin/

For sudo -A, put the export SUDO_ASKPASS=/usr/local/bin/meatproxy-askpass line in the startup file of the shell you start the agent from (~/.zshrc, ~/.bashrc). Then your own commands and the agent's both find the helper. The commit-msg hook is optional; Commit messages shows how to install it.

The tools wait for you. Claude Code lets a tool call run for about 28 hours by default; if MCP_TOOL_TIMEOUT or a per-server timeout is set lower, keep it above timeout_s (both are in milliseconds). More on the helpers in system integration.

What it does not protect against

Programs running as your own user, a command you approve without reading, and plugins in your editor config. The threat model lists all of it.

Similar projects

  • 1Password Environments MCP and op run: stored secrets injected into a process, the agent sees names only.

  • secret-gate: approval over Telegram, secrets from 1Password injected as environment variables.

  • agent-secrets: a secret broker with a hidden prompt or a one-time web form, and output redaction.

  • human-mcp: blocking and async questions to a human; the async pair here follows its idea.

meatproxy stores nothing, asks you on every use, shows the exact command that will receive the value, and draws the window where you already work.

License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI models to interactively prompt users for input or clarification directly through their code editor. It facilitates real-time communication between assistants and users during development tasks.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to request user input through interactive popups in VS Code, supporting button selections, text inputs, and confirmation dialogs. This system allows for seamless human-in-the-loop interactions without interrupting the conversational flow.
    4
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to request human input through native macOS dialogs for clarifying questions and user interactions.
    5 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables agents to request private text or image input from users, run a command once with the submitted values through a one-use grant, and retrieve only user-approved text output.
    Apache 2.0