Skip to main content
Glama
plunger

plunger

Official

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 -F uploads) or a PowerShell Invoke-WebRequest / Invoke-RestMethod command, 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 JavaScript fetch call 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_PROXY and NO_PROXY environment 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?

  1. Undefined-variable safety. Plunger refuses to send a request with an undefined {{variable}}. curl will happily send the placeholder text.

  2. 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].

  3. 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.

  4. 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.

  5. A local audit trail. Every agent request lands in the history you see in the window, tagged MCP or CLI, 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 msstore

Scoop:

scoop bucket add metamug https://github.com/metamug/scoop-bucket
scoop install plunger

pip / 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 anything

macOS (11 or later, Apple Silicon and Intel), Homebrew:

brew install --cask metamug/tap/plunger     # Plunger.app, and a `plunger` command on your PATH

Or 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:

  1. Download plunger-windows.zip and unzip it anywhere.

  2. 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

  1. Paste a URL, or import a curl command.

  2. Press Ctrl+Enter. While a request is in flight, press Escape to cancel waiting for it.

  3. 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 test

Set 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.

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 tools
delete_saved_requestA
Destructive

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_variableA
DestructiveIdempotent

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_workflowB
Destructive

Remove a workflow by name. Returns what was removed.

Inputs: name (required). Returns: name, group, steps, step_count, +1 more

export_curlA
Read-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_historyA
Read-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_entryA
Read-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_requestA
Read-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_requestsA
Read-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_variablesA
Read-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_workflowsA
Read-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_requestA
Idempotent

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_workflowA
Idempotent

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_groupA
Idempotent

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_variableA
Idempotent

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

    A3.9/5.0

    Scored across 17 tools

    Disambiguation4/5

    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.

    Naming Consistency5/5

    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.

    Tool Count4/5

    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.

    Completeness4/5

    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

    ActivityActive
    ResponsivenessSyncing

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      A
      quality
      D
      maintenance
      Universal 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
      -
    • F
      license
      Not graded
      quality
      D
      maintenance
      A 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
      -
    • A
      license
      Not graded
      quality
      C
      maintenance
      A 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