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 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 |
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file llm_mitm_proxy-2026.9.0.tar.gz.
File metadata
- Download URL: llm_mitm_proxy-2026.9.0.tar.gz
- Upload date:
- Size: 5.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3bf79ab43a0eae3d16452ae9e22a8f372d473a59383ae60f545803cbb8c86cce
|
|
| MD5 |
23e88e40792945802659941fe934ecbf
|
|
| BLAKE2b-256 |
1badb44266d87ce4092862ddf86549844451110b694fbe294ee5014ab44573b2
|
Provenance
The following attestation bundles were made for llm_mitm_proxy-2026.9.0.tar.gz:
Publisher:
publish-pypi.yml on mill1000/llm-mitm-proxy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llm_mitm_proxy-2026.9.0.tar.gz -
Subject digest:
3bf79ab43a0eae3d16452ae9e22a8f372d473a59383ae60f545803cbb8c86cce - Sigstore transparency entry: 2787237892
- Sigstore integration time:
-
Permalink:
mill1000/llm-mitm-proxy@f8587406e1dcb9595b8b18ac0509366bf9a90e1f -
Branch / Tag:
refs/tags/2026.9.0 - Owner: https://github.com/mill1000
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@f8587406e1dcb9595b8b18ac0509366bf9a90e1f -
Trigger Event:
release
-
Statement type:
File details
Details for the file llm_mitm_proxy-2026.9.0-py3-none-any.whl.
File metadata
- Download URL: llm_mitm_proxy-2026.9.0-py3-none-any.whl
- Upload date:
- Size: 59.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb2fb5b94e749ab52d3d07c44a7c9130cffc12ea4b0a9fa255c6275e5cbe4116
|
|
| MD5 |
7725a79c921f8b3658db7b174a67a225
|
|
| BLAKE2b-256 |
4db50a686df69abf17975b7b12510581391d0570ba31b9c5ad38f608914e2d5a
|
Provenance
The following attestation bundles were made for llm_mitm_proxy-2026.9.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on mill1000/llm-mitm-proxy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llm_mitm_proxy-2026.9.0-py3-none-any.whl -
Subject digest:
bb2fb5b94e749ab52d3d07c44a7c9130cffc12ea4b0a9fa255c6275e5cbe4116 - Sigstore transparency entry: 2787237998
- Sigstore integration time:
-
Permalink:
mill1000/llm-mitm-proxy@f8587406e1dcb9595b8b18ac0509366bf9a90e1f -
Branch / Tag:
refs/tags/2026.9.0 - Owner: https://github.com/mill1000
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@f8587406e1dcb9595b8b18ac0509366bf9a90e1f -
Trigger Event:
release
-
Statement type: