pwpush-mcp
An MCP server for Password Pusher that allows creating, previewing, and managing self-destructing secret links without retrieving the secret payload.
README
pwpush-mcp
A Model Context Protocol (MCP) server for Password Pusher — create and manage self-destructing secret links from any MCP-compatible client (Claude Desktop, Claude Code, etc.).
Why a "preview but never retrieve" design?
Retrieving a push consumes a view and is irreversible. To keep secrets safe, this server never retrieves a push payload. It can create pushes and hand back the shareable URL, preview that URL (without consuming a view), and manage the lifecycle (expire, audit, list). The secret is only ever read by the human who opens the link.
Tools
| Tool | Description | Auth |
|---|---|---|
create_push |
Create a secret link (text / url / qr / file). Returns the share URL, never the secret. | optional* |
preview_push |
Get a push's share URL without consuming a view. | optional* |
expire_push |
Permanently expire a push. Irreversible. | optional* |
get_push_audit |
View access log (IPs, user agents, events). | token |
list_active_pushes |
List active pushes for the account. | token |
list_expired_pushes |
List expired pushes for the account. | token |
get_version |
Report the instance version and feature flags. | none |
* The bearer token is sent whenever PWPUSH_API_TOKEN is set. Whether it is
required depends on the instance: some allow anonymous push creation, preview,
and expiry (for pushes created with deletable_by_viewer). Listing and audit
are always account-scoped and need a token.
Defaults
New pushes expire after 1 view or 7 days (whichever comes first), with a
retrieval step enabled. Override per call via expire_after_views and duration.
File pushes
Attach one or more local files by passing file_paths; kind is forced to
file and the upload is sent as multipart. payload is optional in that case.
Configuration
Set via environment variables — the API token is never a tool argument:
| Variable | Required | Default | Notes |
|---|---|---|---|
PWPUSH_API_TOKEN |
depends on instance | — | Generate at <base-url>/api_tokens. Always needed for listing/audit. |
PWPUSH_API_EMAIL |
v1 auth only | — | Email tied to the token; legacy (v1) instances auth via X-User-Email + X-User-Token. |
PWPUSH_BASE_URL |
no | https://pwpush.com |
EU: https://eu.pwpush.com. Self-hosted: your domain. |
PWPUSH_API_VERSION |
no | auto |
auto | v1 | v2. Auto-detects the API generation. |
PWPUSH_VERIFY_SSL |
no | true |
Set false only for internal instances with an untrusted cert. |
PWPUSH_CA_BUNDLE |
no | — | Path to a CA bundle (preferred over disabling verification). |
PWPUSH_READ_ONLY |
no | false |
Remove write tools (create_push, expire_push). |
PWPUSH_ENABLED_TOOLS |
no | — | Comma-separated fnmatch allowlist (e.g. list_*,get_version). Empty = all. |
PWPUSH_AUDIT_LOG |
no | true |
Emit one redacted JSON line per write-tool call on stderr. |
PWPUSH_FILE_ROOT |
no | — | Allowlist root for file pushes. Unset = file uploads disabled. When set, create_push(file_paths=…) may only read files under this directory (traversal/symlink escapes rejected). |
MCP_HTTP_TOKEN |
--listen only |
— | Bearer token required on /sse and /messages/. --listen refuses to start without it (see below). |
MCP_HTTP_ALLOW_UNAUTHENTICATED |
no | false |
Opt out of the bearer requirement when fronting the server with your own auth proxy. |
MCP_HTTP_ALLOWED_HOSTS |
no | loopback | Comma-separated Host allowlist (anti-DNS-rebinding). Defaults to localhost,127.0.0.1,[::1] + --host. Use * to allow any. |
PWPUSH_MAX_CONCURRENT |
no | 0 |
Cap concurrent HTTP requests. 0 = unlimited. |
PWPUSH_MAX_RETRIES |
no | 2 |
Retries for connection errors / 429 / 5xx (backoff honours Retry-After). |
PWPUSH_TIMEOUT |
no | 30 |
Per-request HTTP timeout, in seconds. |
Security & multi-tenant
PWPUSH_READ_ONLY=truestrips the write tools entirely — onlypreview_push,get_push_audit,list_*andget_versionremain.expire_pushis the one destructive tool (destructiveHint), so clients can warn on it.PWPUSH_ENABLED_TOOLSnarrows the exposed surface to an allowlist offnmatchglobs, e.g. expose only listing/preview to an auditor.PWPUSH_AUDIT_LOG(on by default) writes one JSON line per write call to thepwpush_mcp.auditlogger on stderr — ship it to Loki/CloudWatch/journald via your runtime. Secrets (payload,passphrase,note,name, file contents, token) are redacted;nameis hashed in the audittargetfor grep-ability. The token is also redacted fromConfigreprs and error text.PWPUSH_FILE_ROOTgates file pushes. File uploads are disabled by default because their bytes become retrievable via the returned share URL — an exfiltration vector for an over-eager or malicious client. Set it to a directory to enable uploads from that subtree only;~expansion and symlink resolution are applied before the containment check, so../traversal and symlink escapes are rejected.
HTTP transport (
--listen) is sensitive. The server holdsPWPUSH_API_TOKENand exposes account-scoped tools. The transport has no TLS and the legacy SSE protocol has no built-in auth, so:
- it binds
127.0.0.1by default — only bind a public interface behind a TLS + auth reverse proxy;- it requires
MCP_HTTP_TOKEN(clients sendAuthorization: Bearer <token>) and refuses to start without it, unless you setMCP_HTTP_ALLOW_UNAUTHENTICATED=true;- it validates the
Hostheader (MCP_HTTP_ALLOWED_HOSTS) to block DNS-rebinding from a browser.
stdiomode is unaffected by all of the above.
API v1 / v2
The server speaks both the modern v2 API (pwpush.com, eu.pwpush.com,
recent self-hosted) and the legacy v1 API (older self-hosted instances).
It auto-detects which one the instance exposes. Note for v1: expiry is
day-granular, so sub-day duration values round up to one day, and file/URL
pushes are only available if the instance enables them.
Both paths are exercised end-to-end: v1 against a live legacy instance,
v2 against pwpush.com (API 2.1). v2 calls target the .json endpoints
deliberately — the suffix-less paths issue a cross-host redirect, so they are
avoided to keep the payload from leaking to another host.
duration accepts a human label (15m, 30m, 45m, 1h, 6h, 12h, 1d,
2d, 3d, 4d, 5d, 6d, 1w, 2w, 3w, 1mo, 2mo, 3mo) or the raw
enum index 0–17.
Install & run
Published as
pwpush-mcpon PyPI andghcr.io/k9fr4n/pwpush-mcpon GHCR, produced by the release workflow on each version tag (latest:v0.3.0).
With uv (recommended):
uvx pwpush-mcp
Or with pipx:
pipx run pwpush-mcp
From source:
pip install -e ".[dev]"
python -m pwpush_mcp
Transports
stdio is the default (Claude Desktop / Claude Code / Docker MCP Gateway). To
expose the server over the network as Streamable-HTTP/SSE:
# Requires MCP_HTTP_TOKEN; binds 127.0.0.1:8000 by default, SSE at /sse.
MCP_HTTP_TOKEN=$(openssl rand -hex 32) pwpush-mcp --listen 8000
# Clients then send: Authorization: Bearer <MCP_HTTP_TOKEN>
Docker
docker run --rm -i \
-e PWPUSH_BASE_URL="https://pwpush.com" \
-e PWPUSH_API_TOKEN="your-token-here" \
ghcr.io/k9fr4n/pwpush-mcp:latest # stdio (default)
HTTP mode via compose.yml (override the entrypoint with --listen):
cp .env.example .env && $EDITOR .env
docker compose up # serves SSE on http://localhost:8000/sse
For v1 (legacy self-hosted) instances also pass -e PWPUSH_API_EMAIL=....
Docker MCP Gateway
The image ships the io.docker.server.metadata label and a catalog entry so the
Docker MCP Gateway can spawn it
natively. See catalog/readme.md:
docker mcp catalog create pwpush-private
docker mcp catalog add pwpush-private pwpush-mcp ./catalog/server.yaml
docker mcp server enable pwpush-mcp
docker mcp gateway run --catalog pwpush-private
Client configuration
Claude Desktop / Claude Code (mcp config)
{
"mcpServers": {
"pwpush": {
"command": "uvx",
"args": ["pwpush-mcp"],
"env": {
"PWPUSH_API_TOKEN": "your-token-here",
"PWPUSH_BASE_URL": "https://eu.pwpush.com"
}
}
}
}
Development
pip install -e ".[dev]"
ruff check src tests && ruff format --check src tests
mypy src
pytest -q --cov=pwpush_mcp --cov-fail-under=80
See CONTRIBUTING.md for the tool/env-var checklists and the release process, and CHANGELOG.md / UPGRADING.md for version history.
License
MIT — see LICENSE.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.