Skip to main content

Fast, lightweight protocol translation hub.

Project description

protoproxy

Fast, lightweight protocol translation hub. Normalizes any supported protocol into a canonical format and re-serializes it out.


Overview

protoproxy sits between a reverse proxy and one or more backend services. Incoming requests — regardless of source protocol — are normalized into a shared canonical Python dict. From there, protoproxy routes and re-serializes into whatever protocol the target backend speaks.

New protocols are two files: an input module that normalizes into the canonical dict, and an output module that translates back out. The core stays untouched.

Currently supports HTTPS, MCP, and WebSocket.

                                     +------------------------------------+
                                     |             protoproxy             |
                                     |                                    |
                                     |  +------------------------------+  |
                                     |  |   auth (bearer validation)   |  |
                                     |  +------------------------------+  |
                                     |                                    |
               +----------+          |  +----------+     +-------------+  |
 Internet <--> |  Nginx   | <------> |  |  https   |     |  canonical  |  |
  (HTTPS)      |  :443    |          |  |  input/  |<--->|    dict     |  |
               |   TLS    |          |  |  output  |     |             |  |
               |Rate limit|          |  +----------+     +-------------+  |
               |          |          |                          ^         |
               +----------+          |                          |         |
                                     |                          v         |
                                     |                   +-------------+  |
                                     |                   |     mcp     |  |
                                     |                   |   input/    |  |
                                     |                   |   output    |  |
                                     |                   +-------------+  |
                                     |                          |         |
                                     +--------------------------+---------+
                                                                |
                                                                v
                                                        +---------------+
                                                        |  MCP Server   |
                                                        |    :9090      |
                                                        +---------------+

protoproxy doesn't replace your reverse proxy — it complements it. Nginx handles TLS termination and rate limiting; protoproxy handles bearer token validation and protocol translation. Only clean, decrypted traffic reaches protoproxy.


How It Works

  1. Reverse proxy terminates TLS, enforces rate limits, and forwards decrypted traffic to protoproxy
  2. The matching input module (e.g. https_input.py) receives the request on its configured port
  3. auth.py validates the bearer token against the server-side secret; unauthorized requests are rejected before any further processing
  4. The input module normalizes the authorized request into a canonical Python dict — a neutral intermediate format every module understands
  5. router.py consults config.json to pick the target output module and dispatches the canonical dict to it
  6. The output module (e.g. mcp_output.py) translates the canonical dict into the target protocol and forwards it to the backend service
  7. The response travels back through the same chain in reverse — backend → output module → canonical dict → input module → reverse proxy → client

Configuration

protoproxy is configured via config.json. Secrets (tokens, keys) go in .env and are never committed.

{
  "inputs": {
    "https": {
      "enabled": true,
      "host": "0.0.0.0",
      "port": 8080
    },
    "mcp": {
      "enabled": true,
      "host": "0.0.0.0",
      "port": 8090
    },
    "websocket": {
      "enabled": true,
      "host": "0.0.0.0",
      "port": 8081
    }
  },
  "outputs": {
    "https": {
      "enabled": true,
      "endpoint": "http://localhost:9080"
    },
    "mcp": {
      "enabled": true,
      "endpoint": "http://localhost:9090"
    },
    "websocket": {
      "enabled": true,
      "endpoint": "ws://localhost:9081"
    }
  },
  "router": {
    "default_output": "mcp"
  }
}

inputs

Each key under inputs is a protocol name, mapped to a listening socket. The protocol name must match a module in src/protoproxy/modules/ (e.g. httpshttps_input.py).

Key Type Description
enabled bool Whether to start this input on launch
host str Interface to bind to. 0.0.0.0 for all interfaces, 127.0.0.1 for localhost only
port int Port to listen on

outputs

Each key under outputs is a protocol name, mapped to a backend destination protoproxy dials when routing. endpoint is a full URL because an output needs scheme + host + port + (optional) path — unlike inputs, which only need a bind target.

Key Type Description
enabled bool Whether to make this output available to the router
endpoint str Full URL of the backend service (e.g. http://localhost:9090, ws://localhost:9081)

router

Key Type Description
default_output str Protocol name to route to when no explicit output is specified by the request

Authentication

protoproxy authenticates incoming requests with a server-side bearer token. Every input module invokes modules/auth.py before normalizing the request; requests without a valid Authorization: Bearer <token> header are rejected with 401 Unauthorized.

The token lives in .env (never committed) and is loaded into the process environment at startup. Comparison is timing-safe (via hmac.compare_digest) to avoid leaking the secret through response-time side channels.

Setup:

  1. Generate a token:
    python -c "import secrets; print(secrets.token_urlsafe(32))"
    
  2. Copy .env.example to .env and paste the value:
    PROTOPROXY_BEARER_TOKEN=your-generated-token-here
    
  3. Share the token out-of-band with any client that needs access.

Client usage:

curl -H "Authorization: Bearer <your-token>" https://your-host/path

Rotating the token is a matter of editing .env and restarting protoproxy. Clients using the old token get 401 immediately.


Installation

pip install protoproxy

Or from source:

git clone https://github.com/geomux/protoproxy.git
cd protoproxy
pip install -e .

Quick Start

python -m protoproxy

protoproxy loads config.json from the working directory and starts one listener per enabled input. With the default config, that's 0.0.0.0:8080 for HTTPS, 0.0.0.0:8090 for MCP, and 0.0.0.0:8081 for WebSocket.


Supported Protocols

  • HTTPS
  • MCP
  • WebSocket

Contributing

Issues and PRs welcome. To add a new protocol, open an issue first to discuss the canonical dict contract before writing code.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

protoproxy-0.0.4.tar.gz (4.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

protoproxy-0.0.4-py3-none-any.whl (6.8 kB view details)

Uploaded Python 3

File details

Details for the file protoproxy-0.0.4.tar.gz.

File metadata

  • Download URL: protoproxy-0.0.4.tar.gz
  • Upload date:
  • Size: 4.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for protoproxy-0.0.4.tar.gz
Algorithm Hash digest
SHA256 46046af2dc5b2ef9135aaeb6314af54bbcc316c98433984ad3384a0d557e9217
MD5 a2e363e5be8acdcd4068dd6887959d9f
BLAKE2b-256 be50d19535c7a9a950a7d65c6bb5d56c26a9569f0d60a05bf217a0f19baee927

See more details on using hashes here.

Provenance

The following attestation bundles were made for protoproxy-0.0.4.tar.gz:

Publisher: publish.yml on geomux/protoproxy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file protoproxy-0.0.4-py3-none-any.whl.

File metadata

  • Download URL: protoproxy-0.0.4-py3-none-any.whl
  • Upload date:
  • Size: 6.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for protoproxy-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 903f91c17ebc2d4413253dcb4a9a9eae8f84bb8879a7267a11b9e4493959c986
MD5 8502fabe938fcc8b11521d7e635577b4
BLAKE2b-256 4c5bf0b5f03887df2b0666c304863e62b74cc0c5f642103ad43f346f989731cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for protoproxy-0.0.4-py3-none-any.whl:

Publisher: publish.yml on geomux/protoproxy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page