Nover
Nover is a typed Python SDK + CLI for self-hosted, multi-provider AI gateways (9Router-compatible). One local endpoint routes to Gemini, NVIDIA, OpenRouter, Groq, Ollama, Tavily and Exa with automatic fallback — and Nover lets you talk to all of it from Python or the terminal: chat (streaming + tool calling), structured JSON output, images, TTS, STT, embeddings and web search/fetch.
$ pip install nover
✨ What you can do
| Capability | SDK method | CLI |
|---|---|---|
| 💬 Chat (streaming) | client.chat() / chat_stream() |
nover chat "..." --stream |
| 🛠️ Tool / function calling | chat(..., tools=...), chat_with_tools() |
via code |
| 📐 Structured output (JSON) | chat(..., response_format=...) |
nover chat --json |
| 🔄 Async | NoverAsync |
— |
| 🌀 Embeddings | client.embeddings() |
nover embed |
| 🖼️ Image generation | client.image() |
nover image |
| 🔊 Text-to-speech | client.tts() |
nover tts |
| 🎙️ Speech-to-text | client.stt() |
nover stt |
| 🔎 Web search | client.web_search() |
nover web search |
| 📄 Fetch URL → markdown | client.web_fetch() |
nover web fetch |
| 🖥️ Interactive chat (TUI) | — | nover interactive |
| 🔌 OpenAI-compatible | from nover import OpenAICompat |
— |
🚀 Quickstart
30 seconds to first chat
$ pip install nover
$ nover chat "Hello, world!" --stream
Chat & tools
from nover import Nover
with Nover() as client:
reply = client.chat("Explain a monad in one sentence")
print(reply.text)
Tool calling:
from nover import Nover, tool
weather = tool("get_weather", "Get weather for a city",
{"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]})
with Nover() as c:
reply = c.chat("What's the weather in Paris?",
tools=[weather],
tool_choice="auto")
print(reply.tool_calls) # None, or [{name, arguments}]
Auto-execute tools with an agent-style loop:
handlers = {"get_weather": lambda args: {"temp": 25}}
reply = c.chat_with_tools("Weather in Paris?", tools=[weather], tool_handler=handlers)
print(reply.text)
Structured output:
reply = c.chat("Return JSON: {\"name\": \"Ada\", \"age\": 36}",
response_format={"type": "json_object"})
print(reply.text) # clean JSON (code fences auto-stripped)
Async
from nover import NoverAsync
import asyncio
async def main():
async with NoverAsync() as c:
return await c.chat("Hi")
print(asyncio.run(main()).text)
Stay with the openai SDK
OpenAICompat is a drop-in: code written against openai keeps working.
from nover import OpenAICompat
client = OpenAICompat()
r = client.chat.completions.create(
model="Code",
messages=[{"role": "user", "content": "Say NOVER"}],
stream=True,
)
for chunk in r:
print(chunk["choices"][0]["delta"].get("content", ""), end="")
Connect ANY AI tool via MCP (Model Context Protocol)
Nover ships a local MCP server so tools like VS Code, Cursor, Claude Desktop and other MCP clients can use your entire gateway.
pip install "nover[mcp]"
nover mcp # serves the MCP server over stdio
It exposes health, models, chat, chat_tool_calls, image, tts,
stt, embeddings, web_search and web_fetch as MCP tools. Add it to a
client, e.g. in VS Code settings.json / Claude Desktop claude_desktop_config.json:
{
"mcpServers": {
"nover": {
"command": "nover",
"args": ["mcp"]
}
}
}
NINEROUTER_URL and NINEROUTER_KEY env vars configure where Nover points.
Images, TTS, STT, embeddings, web — all in one
img = client.image("a watercolor of mountains")
open("mountains.png", "wb").write(img.content)
audio = client.tts("Olá, mundo", voice="pt-BR-FernandaNeural")
open("speech.wav", "wb").write(audio)
text = client.stt(("rec.wav", open("rec.wav", "rb").read()))
print(text.text)
vec = client.embeddings("RAG-ready footnote")[0]
res = client.web_search("9Router open source")
for r in res.results: print(r.title, "-", r.url)
page = client.web_fetch("https://example.com")
print(page.content.text)
🖥️ CLI
nover # help
nover version
nover health # gateway status
nover models --kind chat # list chat models
nover chat "Hello" --stream # chat with streaming
nover interactive # interactive TUI chat
nover embed "text"
nover image "a red fox" --out fox.png
nover tts "Hello" --voice pt-BR-FernandaNeural
nover stt recording.wav
nover web search "9Router"
nover web fetch linkedin.com/p
nover config
ninerouter aliases the same nover CLI for compatibility.
🔧 Configuration
Resolution order: CLI flags > env vars > defaults.
| Setting | Env var | Default |
|---|---|---|
| Base URL | NINEROUTER_URL |
http://localhost:20128 |
| API key | NINEROUTER_KEY |
(optional) |
export NINEROUTER_URL="http://localhost:20128"
export NINEROUTER_KEY="sk-..." # optional if auth disabled
☁️ Into the ecosystem
- OpenAI-compatible:
OpenAICompatswaps into any stack that expectsopenai. - Designed to sit behind LangChain/LiteLLM style routers and orchestrators.
🔒 Privacy & Security
nover is a thin HTTP client. It stores no provider keys, sends your prompts
nowhere except the gateway you configure, and has no telemetry.
- Provider keys live in your gateway, on your machine/VM — not in this library.
- Only tight runtime deps (
httpx,typer), CI-tested across Python 3.9–3.13. - A CI test scans the repo for committed credentials.
See SECURITY.md for details.
📦 Install & develop
pip install -e ".[dev]"
pytest # unit + live tests (live needs gateway)
pip install nover[interactive] # for the TUI
Requires Python 3.9+.
🇧🇷 Português
SDK Python + CLI para gateways de IA multi-provedor self-hosted.
Um único pacote que conversa com um gateway compatível com a API da OpenAI que roteia Gemini, NVIDIA, OpenRouter, Groq, Ollama, Tavily e Exa — com chat, tools, saída estruturada em JSON, imagens, TTS, STT, embeddings e busca web.
pip install "nover"
nover chat "Olá, mundo" --stream
nover interactive
Config, quickstart e CLI são idênticos à seção em inglês acima.
🗺️ Roadmap
See docs/L5_PLAN.md — plan for nover serve (Nover as a standalone gateway).
📄 License
MIT © ChristopherDond
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 nover-2.1.1.tar.gz.
File metadata
- Download URL: nover-2.1.1.tar.gz
- Upload date:
- Size: 237.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae08f476f2e5b5258ef2555ce0787e39e5509ca685da2af1d01982b34fd29080
|
|
| MD5 |
433b1a47936660dc99afa807f8474068
|
|
| BLAKE2b-256 |
64b3b8edfb3c5c4ba00ee2de0eb5a650db61523a8f24031feed4274482e108e3
|
File details
Details for the file nover-2.1.1-py3-none-any.whl.
File metadata
- Download URL: nover-2.1.1-py3-none-any.whl
- Upload date:
- Size: 35.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
addcb1393f496a2391ff7915de704ee7bb4be430acc07cbe94d7ea4c8b7d2d8a
|
|
| MD5 |
5d8e529697cbfb7acc1f06347985800c
|
|
| BLAKE2b-256 |
3e126d0e57ebcb75fe6c061893b5084f6e1559a0ceef5e0efe1bdacc4410dd57
|