plunger
OfficialPlunger is an HTTP client / MCP server that lets an AI agent send API requests safely, save and reuse them, and run multi-step workflows with secret masking and a local audit trail.
Send requests:
send_requestwith method, URL, headers, JSON/raw/form body, variables, timeouts, redirects, TLS options; returns status, timing, size, headers and parsed JSON.Import/export curl:
import_curlparses a curl command (optionally saving it);export_curlturns a saved request or history entry back into curl with{{placeholders}}kept.Manage saved requests:
list_saved_requests,get_saved_request,save_request(withoverwrite),delete_saved_request,set_groupto file them under groups.Manage variables:
set_variable,list_variables,delete_variable— secrets kept in the OS credential store and masked,{{$uuid}},{{$timestamp}}and{{$env:NAME}}built-ins.Workflows:
save_workflow,list_workflows,run_workflow(extract values between steps, asserts, pagination, for-each, polling, retry, jqreturn),delete_workflow.History and audit:
get_history,get_history_entry— see what the user or other agents sent, filtered by source/status/search, tagged gui/cli/mcp.Safety guarantees: refuses undefined
{{variables}}, redacts secrets echoed back, blanks credential headers, never writes secrets to disk unless remembered.
Why?
Sometimes you don't need another platform. You just need to see what the API returned.
AI can write the code. AI can build the pipeline. We still look at the diff before we push. We still look at the logs when something feels wrong. And we still look at the JSON when an API doesn't do what we expected.
Seeing is believing. Plunger is for the moment between "I think it works" and "I can see it works."
Related MCP server: mcp-opentym
What is Plunger?
A small desktop app that sends an HTTP request and shows you what came back.
Request: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS. Params, headers and a Bearer token field.
Body: JSON, XML, form-urlencoded, raw text, or multipart form-data with real file uploads.
Response: status, time and size, the headers, and the body as a collapsible JSON tree. Copy it or save it to a file.
Variables:
{{name}}anywhere in the request, plus{{$uuid}},{{$timestamp}},{{$timestampMs}},{{$isoTimestamp}},{{$randomInt}},{{$randomHex}},{{$randomString}}and{{$env:NAME}}for reading an OS environment variable at send time. A request with an undefined variable is refused, never sent with the placeholder in it.Import and export: paste a curl command (bash or Windows cmd, including
-Fuploads) or a PowerShellInvoke-WebRequest/Invoke-RestMethodcommand, such as DevTools' Copy as cURL or Copy as PowerShell; or open a HAR file. Copy any request back out as curl (bash), curl (Windows cmd), PowerShell or a JavaScriptfetchcall with Ctrl+Shift+C or File > Export request, shown with syntax highlighting.Keep what matters: local history, named saved requests (Ctrl+S) and tabs (Ctrl+T).
Local HTTPS: skip certificate checks for a self-signed dev server, with a warning that stays visible while it's on.
Behind a proxy: Plunger uses your system proxy settings and the
HTTP_PROXY,HTTPS_PROXYandNO_PROXYenvironment variables.Find it again: the sidebar filter searches your whole history and saved requests by URL, method, name or status; right-click a value in a JSON response to copy its path or value.
It's a native program, not a web page, so it reaches whatever your machine can reach: localhost, a dev box on your network, an API that sends no CORS headers.
For AI agents
See the JSON, even when an AI sent the request.
Plunger is built to be driven safely by AI agents, not just clicked by people. The same plunger.exe is also a command-line API client and an MCP server, so an agent like Claude Code sends requests through Plunger's engine instead of running curl. No account, no cloud, no telemetry: now safe for your agents too.
One exe. Human GUI, agent CLI, agent MCP. The same safety guarantees in every mode.
{
"mcpServers": {
"plunger": { "command": "C:\\Tools\\plunger\\plunger.exe", "args": ["mcp"] }
}
}Run plunger install (or File > Set up AI agents... in the window) to register the MCP server in Claude Code, Cursor, Kiro, Codex, Windsurf, VS Code or Gemini CLI and write the always-on steering that tells the agent to use Plunger instead of curl. See docs/agents.md.
Why not just let the agent run curl?
Undefined-variable safety. Plunger refuses to send a request with an undefined
{{variable}}. curl will happily send the placeholder text.Credential isolation. The agent writes
{{token}}and never sees the value. Secrets you've chosen to remember are kept in Windows Credential Manager and filled in by Plunger; if a server echoes one back, it comes back as[redacted:token].Shared human and agent history. You testing in the window and an agent testing from the command line read and write the same saved requests and history.
Structured, typed output. Status, timing, size, headers and the parsed JSON body come back as separate fields, not text the agent has to pick apart.
A local audit trail. Every agent request lands in the history you see in the window, tagged
MCPorCLI, as it happens. curl leaves no record unless you build the logging yourself.
Tools: send_request, import_curl, list_saved_requests, get_history, list_variables, export_curl. From a terminal: plunger send "Saved request name", plunger send --url ..., plunger history. Setup, every tool and option, exit codes and the fine print are in docs/agents.md.
Workflows
When one response feeds the next request (log in, then use the token; look up an id, then act on it), save the steps as a workflow. An agent runs it in one call (run_workflow, or plunger workflow run), and you see it as a flow in the window: a card per step on a rail of connected dots, the values a step hands on written on the connector, and every step lit up as it runs.
Scripts and CI
plunger run script.json runs a file of requests where each step can check its response (asserts) and hand values to the next (extract). It prints a PASS/FAIL line per step, exits non-zero when anything fails, and --junit report.xml writes a test report your CI understands. --env loads variables from a file and --data runs the script once per row of a CSV.
{"steps": [
{"method": "POST", "url": "{{base}}/login", "json": {"username": "demo", "password": "{{password}}"},
"asserts": [{"from": "json:$.token", "type": "string"}],
"extract": [{"name": "token", "from": "json:$.token"}]},
{"url": "{{base}}/me", "headers": {"Authorization": "Bearer {{token}}"},
"asserts": [{"from": "json:$.user", "equals": "demo"}, {"from": "time", "lt": 800}]}
]}Steps can also page through a list (paginate), repeat for each item of a list (for_each), wait for a job (poll), retry after a rate limit (retry), and finish with a return that boils everything collected down to the answer, so an agent reads ten lines instead of two hundred issues. The reshaping is a jq program that cannot touch files, the network or the environment.
There is no scripting language to learn or sandbox to trust: a script is data, so it diffs and reviews like data. And when a job needs real code, a Python or shell script can call plunger send and still get Plunger's secret masking and history. See plunger run --help for every option, docs/scripting.md for every step field with recipes (GitHub, Jira, Slack, waiting for a job, CI), and examples/ for files to copy. Agents get the same guide as the MCP resource plunger://scripting and the build_script prompt.
Small by design
Built in Rust with egui because we wanted a small, fast, native application. No webview, no bundled browser: one exe of about 12 MB, which is also a command-line client and an MCP server for AI agents.
No account to create. No cloud to sync to. The only network traffic is the requests that get sent, by you or by an agent you've connected: no analytics, no telemetry, no update checks. History and saved requests live in one local folder, %APPDATA%\Plunger\data. Bearer tokens and secret variables are never written to a file unless you tick "remember", which keeps them in Windows Credential Manager. Credential-looking headers are blanked before history is saved. Details are in the privacy policy.
Open source
Plunger is MIT licensed. Read it, build it, change it.
A few promises, so you know what you're picking up:
It will never require an account.
It will never add telemetry.
Existing features will never move behind a paywall.
Screenshots
Install
Microsoft Store (signed by Microsoft, no warning, updates itself; it can trail the newest release by a few days): get it here, or
winget install 9P7WRKLN6WHR --source msstoreScoop:
scoop bucket add metamug https://github.com/metamug/scoop-bucket
scoop install plungerpip / uv (Windows, Linux, macOS), from 0.5.1:
pip install plunger-cli # puts a `plunger` command on your PATH
pipx install plunger-cli # same, in its own environment (use this if pip says "externally-managed-environment")
uvx plunger-cli mcp # or run the MCP server without installing anythingmacOS (11 or later, Apple Silicon and Intel), Homebrew:
brew install --cask metamug/tap/plunger # Plunger.app, and a `plunger` command on your PATHOr download Plunger-<version>-macos.dmg from the releases page, open it and drag Plunger to Applications. The first time, right-click the app and choose Open (it is not signed with an Apple Developer ID yet; see docs/packaging-macos.md). pip install plunger-cli also works on a Mac.
Zip:
Download
plunger-windows.zipand unzip it anywhere.Run
plunger.exe.
Windows 10 or 11, 64-bit. The zip isn't code-signed yet, so Windows may say "Windows protected your PC": click More info, then Run anyway. Or build it yourself.
To update the zip, replace the exe. To remove it, delete the exe and %APPDATA%\Plunger.
Usage
Paste a URL, or import a curl command.
Press Ctrl+Enter. While a request is in flight, press Escape to cancel waiting for it.
Read the response.
Press Ctrl+L to focus the URL field and select its contents.
Press Ctrl+F to search the response body: Enter and Shift+Enter (or Next / Prev) step through the matches, Esc closes the box.
With multiple request tabs, Ctrl+Tab moves to the next tab and Ctrl+Shift+Tab moves to the previous one. Cycling wraps at either end.
Build from source
rustup toolchain install stable-x86_64-pc-windows-gnu
rustup default stable-x86_64-pc-windows-gnu
# plus mingw-w64 (gcc, windres, dlltool) on PATH, e.g. from WinLibs or MSYS2
cargo build --release # target/release/plunger.exe
cargo testSet PLUNGER_DATA_DIR to run against a throwaway data folder instead of your real history.
Contributing
Issues and pull requests are welcome. Before adding a feature, ask: does this help someone quickly see what an API is doing? Would someone open Plunger specifically for it? If yes, it probably belongs. Accounts, sync, collaboration and platform features don't.
CONTRIBUTING.md: what fits, how to build, how to send a change.
design.md: how it's built and why.
SECURITY.md: how to report a vulnerability privately.
CODE_OF_CONDUCT.md and the CHANGELOG.
Run cargo test and cargo clippy --all-targets before sending a PR. Maintainers: releases are GitHub releases with plunger-windows.zip attached (push a v* tag).
Available Tools
17 toolsdelete_saved_requestADestructive
Remove a saved request by name (its history entries stay). Returns what was removed.
Inputs: name (required). Returns: url, body, group, method, +7 more
delete_variableADestructiveIdempotent
Remove a variable an agent set (with set_variable). Variables the user defined in the window can only be removed there.
Inputs: name (required). Returns: deleted
delete_workflowBDestructive
Remove a workflow by name. Returns what was removed.
Inputs: name (required). Returns: name, group, steps, step_count, +1 more
export_curlARead-only
Turn a saved request (by name) or a history entry (by id) into a curl command, for CI scripts or tools that only speak curl. {{variables}} stay as placeholders, so no secret is written out.
Inputs: history_id, saved_request.
get_historyARead-only
Recent requests from the shared history, newest first: who sent them (gui = the user, cli or mcp = an agent), method, URL, status and time. Credentials are already blanked. Use it to see what the user tried, or to check what was sent earlier.
Inputs: limit, min_ms, search, source, +2 more. Returns: history
get_history_entryARead-only
One history entry in full: when it was sent, the status and time, and the request as sent (credentials blanked, {{placeholders}} kept, so it can be re-sent or saved). The response body is not stored.
Inputs: id (required). Returns: item, request
get_saved_requestARead-only
One saved request in full: method, URL, headers, body, and the {{variables}} it needs.
Inputs: name (required). Returns: url, body, group, method, +7 more
import_curlA
Parse a curl command into a Plunger request without sending it: method, URL, headers, body and the
{{variables}} it uses. Use it to check what a curl command would do, or with save_as to keep it in the
user's Saved list so it can be sent later with send_request by name.
Inputs: curl (required), save_as. Returns: url, body, group, method, +7 more
list_saved_requestsARead-only
List the requests the user saved in Plunger, by name, with method, URL, headers and the {{variables}} each needs. Call this before building a request from scratch: the user may already have the exact call set up.
Inputs: group. Returns: requests
list_variablesARead-only
List the {{variables}} defined in Plunger. Secret variables are listed by name only (their values are never returned); use them in a request as {{name}} and Plunger fills them in.
Inputs: no named parameters. Returns: built_in, problems, variables, saved_bearer_available
list_workflowsARead-only
List the saved workflows: name, group, how many steps and each step's label. Pass include_steps: true for the
full steps (they are long; ask for them only when you need to read or change one).
Inputs: group, include_steps. Returns: workflows
run_workflowA
Run a saved workflow: its requests are sent in order, values are carried from one response to the next (never shown if secret), and it stops at the first step that fails. Returns each step's status and the variables it set, plus the last response in full.
Inputs: name (required), cleanup, variables, include_last_response. Returns: ok, steps, output, workflow, +5 more
save_requestAIdempotent
Save a request in the user's Saved list without sending it, so it can be re-run by name with send_request
(saved_request). Describe it like send_request. {{placeholders}} are kept as written, including in
Authorization headers. An existing name is refused unless overwrite is true, which replaces it, so a
mistake can be fixed.
Inputs: name (required), url, body, form, +15 more. Returns: url, body, group, method, +7 more
save_workflowAIdempotent
Save a workflow: an ordered list of requests where a later one can use values from an earlier response.
Each step is described like send_request, plus extract (for example {name: "token", from: "json:$.access_token"},
which keeps the value as {{token}} for the steps after it, hidden if it looks like a credential) and
expect_status. Use it for logins, create-then-fetch flows and any sequence you will repeat.
Inputs: name (required), steps (required), group, overwrite. Returns: name, group, steps, step_count, +1 more
send_requestA
Send an HTTP request through Plunger and get back status, timing, size, headers and the parsed JSON body.
Use this instead of curl for API calls: {{variables}} (including the user's secrets, by name) are filled in
for you, an undefined {{variable}} makes the request fail safely instead of sending the placeholder, secret
values are masked in the result, and the request is recorded in the history the user sees in Plunger.
Send a saved request by name with saved_request, or describe one with method, url, headers and a body.
Inputs: url, body, form, json, +12 more. Returns: ok, body, hint, json, +21 more
set_groupAIdempotent
File a saved request or a workflow under a group, such as "Jira" or "Jira/Issues", without touching the
request or workflow itself. An empty group takes it out of its group. Use it to tidy the Saved list.
Inputs: kind (required), name (required), group (required). Returns: kind, name, group
set_variableAIdempotent
Set a variable that later requests use as {{name}}, for example a token you read from a login response. It persists between calls and runs and is shared with the Plunger window, the CLI and other agents. A secret (or a credential-looking name such as token or api_key) is kept in the system credential store and masked in results. A variable the user defined in the window cannot be changed.
Inputs: name (required), value (required), secret. Returns: name, value, secret, source, +2 more
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 17 tools
Most tools map to a distinct resource+action (requests, workflows, variables, history, curl). A few boundaries blur: import_curl with `save_as` overlaps save_request, send_request can dispatch a saved request by name which brushes against run_workflow, and save_request vs save_workflow require reading the description to separate.
Every tool follows a verb_noun snake_case pattern: list_workflows, save_request, get_history_entry, delete_variable, export_curl. The singular/plural distinction between get_history and get_history_entry is also used consistently.
17 tools is slightly above the comfortable band but each cluster (requests, workflows, variables, history, curl import/export, groups) earns its place. No obvious filler tools.
Strong CRUD coverage for saved requests and variables, plus read access to history and workflows. Gaps: no in-place update for workflows (save_request has `overwrite`, save_workflow appears not to) and no way to delete or prune history entries, forcing delete-and-recreate workarounds.
Maintenance
Related MCP Connectors
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.
Build, validate, deploy — HTTP APIs, cron jobs, webhooks and MCP tools — from your AI client.
Related MCP Servers
- FlicenseAqualityDmaintenanceUniversal HTTP client tool for LLM agents. Enables Claude and other MCP-compatible agents to perform GET, POST, PUT, DELETE, and other HTTP requests to any URL, including localhost and internal network addresses.2-
- FlicenseNot gradedqualityDmaintenanceA lightweight MCP HTTP server giving AI assistants real tools to interact with your Windows machine, including running commands, file access, system info, web search, and browser automation.1-
- AlicenseNot gradedqualityCmaintenanceA tiny local MCP server and CLI that lets AI agents read only allowlisted environment variables, redacts known secrets from text, and logs every access.MIT
- AlicenseNot gradedqualityBmaintenanceRemote-first, model-independent Windows execution MCP for ChatGPT, Claude, Gemini, and other MCP-compatible AI clients.MIT