Skip to main content

MLPal Gateway

One API for every model provider.
Anthropic, OpenAI, Google, and AWS Bedrock ship built in; new providers are an adapter away.
Self-hosted. Model routing, per-request cost metering, per-key access control, admin console.

PyPI License CI Python


Gateway console


Quick start

cp .env.oss.example .env      # add whichever provider keys you have
docker compose up             # Postgres + Redis + gateway + admin console
Gateway http://localhost:8000 — Swagger at /docs
Admin console http://localhost:8080
Bootstrap admin key printed once: docker compose logs seed

Adapters activate based on which provider keys you set. GET /v1/models lists only what your box can serve; a single-provider deployment works without any extra configuration.

Don't want to run infrastructure? The managed deployment of this same codebase runs at mlpal.ai — create a key there and point the same SDK/CLI at https://models.mlpal.ai instead of localhost.

Calling it

Anthropic wire, any provider's model:

curl http://localhost:8000/v1/messages \
  -H "Authorization: Bearer $MLPAL_KEY" -H "content-type: application/json" \
  -d '{"model":"mlpal","max_tokens":512,"messages":[{"role":"user","content":"hi"}]}'

Existing OpenAI SDK code — point it at http://localhost:8000/v1. Python SDK — pip install mlpal-assistants:

from mlpal_assistants import MLPal

client = MLPal(base_url="http://localhost:8000")   # key from MLPAL_API_KEY
msg = client.messages.create(
    model="mlpal", max_tokens=512,
    messages=[{"role": "user", "content": "Hello"}],
)
print(msg.text, msg.compute_units)

What you get

  • One wire format for every provider. POST /v1/messages speaks the Anthropic Messages format for all served models; the gateway translates to each provider's native API and relays the SSE stream without re-chunking. OpenAI-compatible endpoints (/v1/chat/completions, embeddings, images, audio) serve existing OpenAI SDK code unchanged.
  • Router tags. "model": "mlpal" resolves to the best model your deployment serves, walking a curated candidate list that spans providers. Model retired? Provider key missing? Resolution falls through to the next candidate. Client code never changes.
  • Cost on every response. Requests are metered in compute units (1 CU = $10 of provider list price, no markup) and returned in an X-MLPal-Compute-Units header. The meter reproduces provider list pricing exactly, including prompt-cache discounts.
  • Per-key control. Model-policy globs (allow: ["claude-*"]), multi-window spend budgets, permissions — all enforced at admission, before the provider call. A running stream is never cut.
  • Observability. Per-key cache hit rate, latency p50/p95, time-to-first-token, request traces, and optional payload capture (zlib-compressed, runtime toggle — your box, your data).
  • Provider semantics preserved. Prompt caching (cache_control), tools, structured output, and MCP config pass through untouched.

Measured

Gateway overhead isolated against a zero-latency fake upstream, so provider variance can't hide anything — MLPal with its full admission pipeline (auth, rate limit, billing, model policy, budgets, metering, capture) against LiteLLM in both its bare mode and a production configuration with database-backed virtual keys, budgets, and spend tracking (N=100 per system; methodology in the technical report, raw data and harness in paper/bench/):

Gateway overhead benchmark

+8.5 ms with everything on — less than a bare proxy checks one static key for, and with the tightest tail (p95 33 ms vs 58/41 ms). Admission-time governance is computationally free. Provider semantics survive the hop too: a 22k-token cached prefix passes through byte-faithfully and metered 0.002756 CU on write, 0.000224 CU on read (12.3×) — matching Anthropic's list price to five decimals. The managed deployment of this same codebase, measured the same night from the same client, served claude-haiku-4.5 at 642 ms median TTFT vs OpenRouter's 898 ms (report §5.3–5.4).

Why a curated catalog

Production models retire on roughly a 12-month cycle now — from the providers' own deprecation ledgers:

Model launch-to-retirement spans

Serving a model well — valid parameter ranges, per-model cache minimums, reasoning budgets, provider quirks — is per-model engineering that does not scale to a 1,600-entry catalog. This gateway serves a curated set (~75 models) kept current by a data feed, and router tags absorb every retirement above server-side. You can always pin any explicit model tag or register your own adapter.

The full argument with benchmarks and sources: Curation Over Breadth · feature matrix vs. OpenRouter / LiteLLM / Portkey: docs/POSITIONING.md.

Router tags vs. catalog

Two ways to use the curated set — they differ in who picks the model:

Router tags — mlpal, mlpal-flash, mlpal-lite Catalog — GET /v1/catalog
Who decides The gateway: tag resolves to the best served model for the operation Your client: a ranked list with tiers, capabilities, per-token rates
Use when You want a good default and zero model-name maintenance You are writing routing logic (agents route sub-tasks this way)
One-provider box Falls through to whatever your key serves Unserved candidates are marked

Both are driven by the same feed (catalog/*.json) and update as data, not code.

API surface

Endpoint Purpose
POST /v1/messages Anthropic-wire inference, all providers, streaming SSE
POST /v1/chat/completions OpenAI-compatible chat
/v1/embeddings · /v1/images/generations · /v1/audio/* OpenAI-compatible modalities
GET /v1/models Models this deployment serves
GET /v1/catalog Ranked catalog: tiers, capabilities, rates
POST /v1/feedback Outcome feedback for routing scores
GET /v1/usage/* · /v1/keys/* Self-scoped usage, traces, per-key stats
/admin/v1/* Keys, policies, budgets, capture, routing

Details: docs/API_SURFACE.md.

Use it with a coding agent

Yodex is a coding CLI built on this gateway — it speaks the Anthropic wire and uses GET /v1/catalog to route sub-tasks to cheaper models (~10× lower sub-agent cost in its benchmarks):

npm install -g @mlpal/yodex
export YODEX_GATEWAY_URL=http://localhost:8000
export YODEX_API_KEY=mlpal_sk_...    # minted in the console
yodex "fix the failing test"

Repository layout

src/                 # FastAPI gateway: adapters, services, api, seams
console/             # admin UI (React + Vite): keys, traces, catalog, usage
docker-compose.yaml  # one-command local deployment
alembic/             # database migrations
paper/               # technical report + benchmark harness + raw results
enterprise/          # commercial add-ons (separate license, NOT Apache)
docs/                # API surface, positioning, figures

Auth and billing sit behind composition-root seams (api/mounting.py); the defaults (MLPAL_AUTH_BACKEND=local, MLPAL_BILLING_BACKEND=local) run fully standalone with no external dependencies. src/ never imports from enterprise/.

License and contact

Apache-2.0, except the enterprise/ directory (commercial — see enterprise/LICENSE). Contributions welcome: CONTRIBUTING.md · security and everything else: contact@mlpal.ai

Download files

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

Source Distribution

mlpal_gateway-0.2.3.tar.gz (1.2 MB view details)

Uploaded Source

Built Distribution

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

mlpal_gateway-0.2.3-py3-none-any.whl (314.0 kB view details)

Uploaded Python 3

File details

Details for the file mlpal_gateway-0.2.3.tar.gz.

File metadata

  • Download URL: mlpal_gateway-0.2.3.tar.gz
  • Upload date:
  • Size: 1.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.9

File hashes

Hashes for mlpal_gateway-0.2.3.tar.gz
Algorithm Hash digest
SHA256 cf1797a377a0d646fdec2963441a9358a8115e4814c5ab52287fa408ffc9b673
MD5 b5b7ac9b942d820d35de5cf46789a144
BLAKE2b-256 bbd72af4b21a3414d477276e042cbe982914d028ef820af5d9a3504a2d06cdbe

See more details on using hashes here.

File details

Details for the file mlpal_gateway-0.2.3-py3-none-any.whl.

File metadata

File hashes

Hashes for mlpal_gateway-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 ce7e12be69632d58b92a1acc4323ccc754d46e7ff37e6fe668229a3aa98f90a3
MD5 9bf8a96b3124f12eef519638191232ea
BLAKE2b-256 96c37800824a157a23776fd8e3a70d3206ffada5fa5a51dea7a1e956d231da7a

See more details on using hashes here.

Supported by

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