Liter-LLM Universal LLM Client
Liter-LLM is a universal LLM API client with a Rust core and native bindings for
Python, TypeScript/Node.js, Go, Java, C#, Ruby, PHP, Elixir, WebAssembly, and C
(FFI). One unified interface reaches 143 providers (OpenAI, Anthropic, Google
Gemini, Groq, Mistral, Cohere, AWS Bedrock, Azure, and many more).
Capability map
- Modalities — chat completions, streaming, tool/function calling,
structured outputs, embeddings, image generation, audio (speech,
transcription), moderation, web search, OCR, reranking, batch,
and file operations.
- Provider routing —
provider/model prefix selects the backend
(openai/gpt-4o, anthropic/claude-sonnet-4-20250514,
google/gemini-2.0-flash). Set model_hint to skip the prefix.
- Middleware — response caching, rate limiting (RPM/TPM), cost tracking,
budget enforcement (
hard / soft), fallback chains, circuit-breaker
cooldown, and background health checks.
- Search providers (12) and OCR providers (4) — first-class
search
and ocr methods routed by the same prefix convention.
- Proxy server —
liter-llm api exposes an OpenAI-compatible gateway with
22 REST endpoints, virtual API keys, budgets, and SSE streaming.
- MCP server —
liter-llm mcp exposes 22 tools mirroring the proxy
endpoints, for MCP-compatible clients (Claude Code, Claude Desktop).
- 14 language bindings — same surface, language-native naming (snake_case
for Python/Rust/Ruby/Go/Elixir/PHP, camelCase for TS/Node/WASM/C#/Java).
When to use the MCP server vs the SDK vs the proxy
| Use the … |
When you want to … |
Entry point |
| MCP server |
Let the agent call LLM APIs directly as tools, with no glue code |
liter-llm mcp --transport stdio (this plugin auto-registers it) |
| SDK / binding |
Write application code that calls LLMs in a specific language |
pip install liter-llm, cargo add liter-llm, etc. |
| Proxy |
Give many apps/teams a shared OpenAI-compatible endpoint with keys, budgets, and rate limits |
liter-llm api --config liter-llm-proxy.toml |
Rule of thumb: reach for the MCP server inside an agent session; the SDK when
building software; the proxy when centralizing access for multiple consumers.
Installation
CLI (proxy + MCP server)
# Homebrew (macOS / Linux)
brew install xberg-io/tap/liter-llm
# or run it without a persistent install (the CLI proxy package self-installs the binary)
npx @xberg-io/liter-llm-cli --help
uvx --from liter-llm-cli liter-llm --help
# or download a prebuilt binary from the latest GitHub release:
# https://github.com/xberg-io/liter-llm/releases/latest
# or build from source
cargo install liter-llm-cli
# or Docker (35MB image)
docker pull ghcr.io/xberg-io/liter-llm
Language bindings
| Language |
Install |
| Python |
pip install liter-llm |
| Node.js |
pnpm add @xberg-io/liter-llm |
| Rust |
cargo add liter-llm |
| Go |
go get github.com/xberg-io/liter-llm/packages/go |
| Ruby |
gem install liter_llm |
| PHP |
composer require xberg-io/liter-llm |
| C# |
dotnet add package XbergIo.LiterLlm |
| WASM |
pnpm add @xberg-io/liter-llm-wasm |
Quick start (Python, async)
import asyncio
import os
from liter_llm import create_client
from liter_llm._internal_bindings import ChatCompletionRequest
async def main() -> None:
client = create_client(api_key=os.environ["OPENAI_API_KEY"])
request = ChatCompletionRequest.from_json(
'{"model":"openai/gpt-4o","messages":[{"role":"user","content":"Hello!"}]}'
)
response = await client.chat(request)
print(response.choices[0].message.content)
asyncio.run(main())
Provider routing
The prefix before / in the request's model selects the provider:
ChatCompletionRequest.from_json('{"model":"openai/gpt-4o","messages":[...]}')
ChatCompletionRequest.from_json('{"model":"anthropic/claude-sonnet-4-20250514","messages":[...]}')
ChatCompletionRequest.from_json('{"model":"google/gemini-2.0-flash","messages":[...]}')
ChatCompletionRequest.from_json('{"model":"groq/llama3-70b","messages":[...]}')
API keys come from environment variables: OPENAI_API_KEY, ANTHROPIC_API_KEY,
GEMINI_API_KEY, GROQ_API_KEY, MISTRAL_API_KEY, CO_API_KEY, and AWS
credentials for Bedrock.
Configuration
Pass basic options to create_client(...) (api_key, base_url,
timeout_secs, max_retries, model_hint), or set the full surface in a
liter-llm.toml (SDK) / liter-llm-proxy.toml (proxy) — both auto-discover
from the cwd upward.
# liter-llm.toml
api_key = "${OPENAI_API_KEY}"
model_hint = "openai"
timeout_secs = 120
max_retries = 5
[cache]
max_entries = 512
ttl_seconds = 600
[budget]
global_limit = 50.0
enforcement = "hard"
[rate_limit]
rpm = 60
tpm = 100000
| Option |
Default |
Description |
api_key |
required |
Provider key, wrapped in SecretString (never logged). |
base_url |
from registry |
Override the provider base URL. |
model_hint |
none |
Pre-resolve a provider, skipping the prefix lookup. |
timeout_secs |
60 |
Request timeout in seconds. |
max_retries |
3 |
Retries on 429/5xx with exponential backoff. |
cache |
none |
max_entries, ttl_seconds. |
budget |
none |
global_limit, model_limits, enforcement. |
rate_limit |
none |
rpm, tpm. |
cost_tracking |
false |
Per-request cost tracking. |
tracing |
false |
OpenTelemetry spans. |
Proxy server
liter-llm api --config liter-llm-proxy.toml
22 OpenAI-compatible endpoints, model routing by prefix, virtual API keys,
per-key RPM/TPM limits, cost tracking, budget enforcement, response caching, SSE
streaming, and an OpenAPI 3.1 spec at /openapi.json.
MCP server
liter-llm mcp --transport stdio # for Claude Code / Claude Desktop
liter-llm mcp --transport http --port 3001
This plugin auto-registers the stdio server via scripts/mcp-launch.sh. The 22
tools mirror the proxy endpoints: chat, embed, generate_image, speech,
transcribe, moderate, rerank, search, ocr, list_models; file ops
(create_file, list_files, retrieve_file, delete_file, file_content);
batch ops (create_batch, list_batches, retrieve_batch, cancel_batch);
and Responses API (create_response, retrieve_response, cancel_response).
Common pitfalls
- Provider prefix is required — use
"provider/model" unless model_hint
is set, or routing fails.
- API keys are SecretString — never logged or serialized. Read from env
vars; never hardcode.
- Python methods are async —
await inside an async context.
- Naming conventions differ — camelCase for TS/Node/WASM/C#/Java,
snake_case elsewhere.
- Streaming chunks may have null content — null-check
chunk.choices[0].delta.content before use.
- Budget modes —
hard rejects over-budget requests; soft logs and
allows.
Additional resources
1---2name: liter-llm3description: Universal LLM API client for 143 providers with native bindings for 14 languages. Use when writing code that calls LLM APIs via liter-llm in Python, TypeScript, Rust, Go, Java, C#, Ruby, PHP, Elixir, WASM, or C, when running the OpenAI-compatible proxy, or when calling LLMs through the MCP server. Covers chat, streaming, tool calling, embeddings, image generation, speech, transcription, moderation, web search, OCR, reranking, provider routing, middleware, and configuration.4license: MIT5---67<!--8AI-RULEZ :: GENERATED FILE — DO NOT EDIT9Content-Hash: blake3:2fa27fd4d771d530a072afc9c10f24123280b69a3eb09f1b06f58abdba7b451110Source-Hash: blake3:994b83e19a30ce07bfdfeb4caf56e995dc024de32e00f13b45cd995d0e44108611Schema-Version: v112-->1314# Liter-LLM Universal LLM Client1516Liter-LLM is a universal LLM API client with a Rust core and native bindings for17Python, TypeScript/Node.js, Go, Java, C#, Ruby, PHP, Elixir, WebAssembly, and C18(FFI). One unified interface reaches 143 providers (OpenAI, Anthropic, Google19Gemini, Groq, Mistral, Cohere, AWS Bedrock, Azure, and many more).2021## Capability map2223- **Modalities** — chat completions, streaming, tool/function calling,24 structured outputs, embeddings, image generation, audio (speech,25 transcription), moderation, web search, OCR, reranking, batch,26 and file operations.27- **Provider routing** — `provider/model` prefix selects the backend28 (`openai/gpt-4o`, `anthropic/claude-sonnet-4-20250514`,29 `google/gemini-2.0-flash`). Set `model_hint` to skip the prefix.30- **Middleware** — response caching, rate limiting (RPM/TPM), cost tracking,31 budget enforcement (`hard` / `soft`), fallback chains, circuit-breaker32 cooldown, and background health checks.33- **Search providers (12)** and **OCR providers (4)** — first-class `search`34 and `ocr` methods routed by the same prefix convention.35- **Proxy server** — `liter-llm api` exposes an OpenAI-compatible gateway with36 22 REST endpoints, virtual API keys, budgets, and SSE streaming.37- **MCP server** — `liter-llm mcp` exposes 22 tools mirroring the proxy38 endpoints, for MCP-compatible clients (Claude Code, Claude Desktop).39- **14 language bindings** — same surface, language-native naming (snake_case40 for Python/Rust/Ruby/Go/Elixir/PHP, camelCase for TS/Node/WASM/C#/Java).4142## When to use the MCP server vs the SDK vs the proxy4344| Use the … | When you want to … | Entry point |45|-----------|--------------------|-------------|46| **MCP server** | Let the agent call LLM APIs directly as tools, with no glue code | `liter-llm mcp --transport stdio` (this plugin auto-registers it) |47| **SDK / binding** | Write application code that calls LLMs in a specific language | `pip install liter-llm`, `cargo add liter-llm`, etc. |48| **Proxy** | Give many apps/teams a shared OpenAI-compatible endpoint with keys, budgets, and rate limits | `liter-llm api --config liter-llm-proxy.toml` |4950Rule of thumb: reach for the MCP server inside an agent session; the SDK when51building software; the proxy when centralizing access for multiple consumers.5253## Installation5455### CLI (proxy + MCP server)5657```bash58# Homebrew (macOS / Linux)59brew install xberg-io/tap/liter-llm6061# or run it without a persistent install (the CLI proxy package self-installs the binary)62npx @xberg-io/liter-llm-cli --help63uvx --from liter-llm-cli liter-llm --help6465# or download a prebuilt binary from the latest GitHub release:66# https://github.com/xberg-io/liter-llm/releases/latest6768# or build from source69cargo install liter-llm-cli7071# or Docker (35MB image)72docker pull ghcr.io/xberg-io/liter-llm73```7475### Language bindings7677| Language | Install |78|----------|---------|79| Python | `pip install liter-llm` |80| Node.js | `pnpm add @xberg-io/liter-llm` |81| Rust | `cargo add liter-llm` |82| Go | `go get github.com/xberg-io/liter-llm/packages/go` |83| Ruby | `gem install liter_llm` |84| PHP | `composer require xberg-io/liter-llm` |85| C# | `dotnet add package XbergIo.LiterLlm` |86| WASM | `pnpm add @xberg-io/liter-llm-wasm` |8788## Quick start (Python, async)8990```python91import asyncio92import os93from liter_llm import create_client94from liter_llm._internal_bindings import ChatCompletionRequest9596async def main() -> None:97 client = create_client(api_key=os.environ["OPENAI_API_KEY"])98 request = ChatCompletionRequest.from_json(99 '{"model":"openai/gpt-4o","messages":[{"role":"user","content":"Hello!"}]}'100 )101 response = await client.chat(request)102 print(response.choices[0].message.content)103104asyncio.run(main())105```106107## Provider routing108109The prefix before `/` in the request's `model` selects the provider:110111```python112ChatCompletionRequest.from_json('{"model":"openai/gpt-4o","messages":[...]}')113ChatCompletionRequest.from_json('{"model":"anthropic/claude-sonnet-4-20250514","messages":[...]}')114ChatCompletionRequest.from_json('{"model":"google/gemini-2.0-flash","messages":[...]}')115ChatCompletionRequest.from_json('{"model":"groq/llama3-70b","messages":[...]}')116```117118API keys come from environment variables: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`,119`GEMINI_API_KEY`, `GROQ_API_KEY`, `MISTRAL_API_KEY`, `CO_API_KEY`, and AWS120credentials for Bedrock.121122## Configuration123124Pass basic options to `create_client(...)` (`api_key`, `base_url`,125`timeout_secs`, `max_retries`, `model_hint`), or set the full surface in a126`liter-llm.toml` (SDK) / `liter-llm-proxy.toml` (proxy) — both auto-discover127from the cwd upward.128129```toml130# liter-llm.toml131api_key = "${OPENAI_API_KEY}"132model_hint = "openai"133timeout_secs = 120134max_retries = 5135136[cache]137max_entries = 512138ttl_seconds = 600139140[budget]141global_limit = 50.0142enforcement = "hard"143144[rate_limit]145rpm = 60146tpm = 100000147```148149| Option | Default | Description |150|--------|---------|-------------|151| `api_key` | required | Provider key, wrapped in `SecretString` (never logged). |152| `base_url` | from registry | Override the provider base URL. |153| `model_hint` | none | Pre-resolve a provider, skipping the prefix lookup. |154| `timeout_secs` | 60 | Request timeout in seconds. |155| `max_retries` | 3 | Retries on 429/5xx with exponential backoff. |156| `cache` | none | `max_entries`, `ttl_seconds`. |157| `budget` | none | `global_limit`, `model_limits`, `enforcement`. |158| `rate_limit` | none | `rpm`, `tpm`. |159| `cost_tracking` | false | Per-request cost tracking. |160| `tracing` | false | OpenTelemetry spans. |161162## Proxy server163164```bash165liter-llm api --config liter-llm-proxy.toml166```16716822 OpenAI-compatible endpoints, model routing by prefix, virtual API keys,169per-key RPM/TPM limits, cost tracking, budget enforcement, response caching, SSE170streaming, and an OpenAPI 3.1 spec at `/openapi.json`.171172## MCP server173174```bash175liter-llm mcp --transport stdio # for Claude Code / Claude Desktop176liter-llm mcp --transport http --port 3001177```178179This plugin auto-registers the stdio server via `scripts/mcp-launch.sh`. The 22180tools mirror the proxy endpoints: `chat`, `embed`, `generate_image`, `speech`,181`transcribe`, `moderate`, `rerank`, `search`, `ocr`, `list_models`; file ops182(`create_file`, `list_files`, `retrieve_file`, `delete_file`, `file_content`);183batch ops (`create_batch`, `list_batches`, `retrieve_batch`, `cancel_batch`);184and Responses API (`create_response`, `retrieve_response`, `cancel_response`).185186## Common pitfalls1871881. **Provider prefix is required** — use `"provider/model"` unless `model_hint`189 is set, or routing fails.1902. **API keys are SecretString** — never logged or serialized. Read from env191 vars; never hardcode.1923. **Python methods are async** — `await` inside an async context.1934. **Naming conventions differ** — camelCase for TS/Node/WASM/C#/Java,194 snake_case elsewhere.1955. **Streaming chunks may have null content** — null-check196 `chunk.choices[0].delta.content` before use.1976. **Budget modes** — `hard` rejects over-budget requests; `soft` logs and198 allows.199200## Additional resources201202- Upstream docs: <https://docs.liter-llm.xberg.io>203- GitHub: <https://github.com/xberg-io/liter-llm>