llm-mitm-proxy
A simple transparent MITM proxy for LLM APIs with a live Web UI for inspecting, replaying, and exporting "conversations" between clients and an upstream server.
Trusted Networks and/or Testing Only
There is no authentication, no SSL/TLS termination, or other "reverse proxy" feature set. Its primary intent is to provide visibility between an agent and the server.
Client Identification
Clients are identified by their source IP, user agent, and API key (if provided), which determines which "conversation" traffic appears under in the Web UI. An API key is not required, IP and user agent are enough to tell many clients apart, but an API key can be used as a further split for clients sharing the same IP, and user agent.
Dissectors
The proxy forwards all traffic verbatim and decodes requests and responses for the Web UI with per-request dissectors that match on method + path.
Supported dissectors:
openai: OpenAI-compatible chat completionsgeneric: everything else, captured as raw data
Vibe Warning
This project was entirely vibe coded with Qwen 3.8 27B and the Zed Agent on local hardware.
Work proceeded milestone by milestone according to the PLAN.md with design, key decisions, and open questions. Occasional updates were made to the plan as direction shifted. Each milestone was tested against a llama.cpp server by a human before committed.
The full agent conversation log is preserved in CONVERSATION.md.
Quick Start
Docker Compose
services:
llm-mitm-proxy:
image: ghcr.io/mill1000/llm-mitm-proxy:latest
restart: unless-stopped
ports:
- "8081:8081" # LLM API
- "9090:9090" # Web UI
environment:
UPSTREAM_BASE_URL: "http://<your-llamacpp>:8080"
extra_hosts:
- "host.docker.internal:host-gateway"
Docker
docker run -d --name llm-mitm-proxy -p 8081:8081 -p 9090:9090 -e UPSTREAM_BASE_URL=http://<your-llamacpp>:8080 ghcr.io/mill1000/llm-mitm-proxy:latest
pipx/uvx
# uvx
uvx llm-mitm-proxy http://<your-llamacpp>:8080
# pipx
pipx install llm-mitm-proxy
llm-mitm-proxy http://<your-llamacpp>:8080
Usage
- Start the proxy
- Point an agent at the proxy
- Open the Web UI and look at the requests go brrr.
See Configuration for more information on specifying an upstream API key, changing ports, and other options.
Configuration
Command Line
usage: llm-mitm-proxy [-h] [--version] [--host HOST] [--proxy-port PORT] [--web-port PORT]
[--upstream-api-key KEY] [--log-level LEVEL] [--ui-dir DIR]
[UPSTREAM_BASE_URL]
| Arg | Notes |
|---|---|
UPSTREAM_BASE_URL (positional) |
upstream base URL (default http://host.docker.internal:8080) |
--host |
listen host for both listeners (default 0.0.0.0) |
--proxy-port |
proxy listener port (default 8081, the transparent catch-all; llama.cpp's own default is 8080) |
--web-port |
WebUI + /api/* + /ws + /health listener port (default 9090) |
--upstream-api-key |
optional server-side fallback key, injected only when a client sends no key |
--log-level |
app loggers, incl. the llm_proxy.ws connection trace at debug (connect/focus/disconnect) |
--ui-dir |
static UI directory (default: the in-package llm_proxy/web build) |
--help / --version |
usage / package version |
Docker Environment Variables
The Docker image maps the following environment variables to command line options:
| Var | CLI arg |
|---|---|
UPSTREAM_BASE_URL |
positional upstream |
UPSTREAM_API_KEY |
--upstream-api-key |
LISTEN_HOST |
--host |
PROXY_PORT |
--proxy-port |
WEB_PORT |
--web-port |
LOG_LEVEL |
--log-level |
Metadata
Release files for llm-mitm-proxy 2026.9.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| llm_mitm_proxy-2026.9.1.tar.gz | 5.2 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| llm_mitm_proxy-2026.9.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.3 MB
Release files / llm_mitm_proxy-2026.9.1.tar.gz
| Download URL | llm_mitm_proxy-2026.9.1.tar.gz |
|---|---|
| Size | 5.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
40bb2b61f7362ab14d0e00c8e43ab2f1d92e7036b849a1cff621a962f53d84ec
|
|
BLAKE2b-256 checksum How to use checksums |
339c409127915a1a015f3d0ecdbcd2c986fea75b78b100da5dac4f7a8f2f13b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.
Transparency logRelease files / llm_mitm_proxy-2026.9.1-py3-none-any.whl
| Download URL | llm_mitm_proxy-2026.9.1-py3-none-any.whl |
|---|---|
| Size | 60.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
64b3918e93a9acbeb4e6ba773ecfd0db8cbe5df7caf9a437f13b4a44aac0a680
|
|
BLAKE2b-256 checksum How to use checksums |
38acc7d5e6b0db90bb761b20faaf5c429e8c4b97b84a21f3420b65534c52774b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.
Transparency log