ovos-translate-server — HTTP Translation Server¶
In a nutshell
This is a small standalone program. It puts OVOS's language tools online as a web service: translating text between languages, and guessing what language a piece of text is in. Other devices send it text over a simple web request and get back the translation (or the detected language), so one machine can do this work for many. It can also imitate popular translation services (like DeepL, Google Translate, or LibreTranslate), so software written for those works against your own server unchanged. See Translation Plugins and the Glossary.
What it Does¶
ovos-translate-server wraps any OVOS translation plugin and language-detection plugin. It exposes them as a FastAPI HTTP service (served by uvicorn). It is the standard way to make OVOS language plugins available to remote clients, or to use them as a microservice in a Docker-based deployment.
The companion client plugin ovos-translate-server-plugin can point an OVOS device at this server so that translation and language detection are offloaded from the device. Left unconfigured, that client plugin falls back to a built-in list of public community-run servers rather than failing (see Translation Plugins). Set it to your own server, deployed as taught below, for anything beyond a quick test.
Community servers are best-effort demos
The public OVOS servers exist for easy onboarding and demos only. They are best-effort, not optimized, carry no uptime guarantees, and may vanish at any time. OVOS will be slow and unreliable if you rely on them. The official recommendation is to self-host — or skip servers entirely: fully offline plugins exist for everything.
Installation¶
A bare pip install ovos-translate-server gets an unusable release
Without --pre and a floor pin, pip resolves the name to the latest stable release,
0.0.2, which is years behind the 0.10.0a1 line this page documents. It looks
installed and serves nothing described here. After installing, confirm what you actually
got: pip show ovos-translate-server.
Also install the translation plugin(s) you intend to serve:
pip install ovos-translate-plugin-nllb
pip install --pre ovos-lang-detector-classics-plugin pycld2 langdetect fastlang
Running the Server¶
Command Line¶
ovos-translate-server \
--tx-engine ovos-translate-plugin-nllb \
--detect-engine ovos-lang-detector-plugin-voter \
--host 0.0.0.0 \
--port 9686
CLI arguments:
| Argument | Default | Description |
|---|---|---|
--tx-engine |
required | OPM translation plugin (opm.lang.translate) entry-point name |
--detect-engine |
None |
OPM language detection plugin (opm.lang.detect) entry-point name (optional) |
--host |
0.0.0.0 |
Host to bind |
--port |
9686 |
TCP port |
If --detect-engine is omitted, no dedicated detection plugin is loaded. /detect and /classify fall back to the translation plugin's own detect() / detect_probs() methods.
Python API¶
import uvicorn
from ovos_translate_server import start_translate_server
app, engine = start_translate_server(
tx_engine="ovos-translate-plugin-nllb",
detect_engine="ovos-lang-detector-plugin-voter",
)
uvicorn.run(app, host="0.0.0.0", port=9686)
start_translate_server() loads the plugins and returns (app, engine) where app is a FastAPI application. You run it with uvicorn (the ovos-translate-server CLI does exactly this). The translate and detect plugins receive their own section from mycroft.conf — translation.<plugin> and language_detection.<plugin> respectively — falling back to {} when nothing is configured, so model paths and other plugin settings in mycroft.conf are honored.
HTTP API Endpoints¶
All endpoints accept GET requests. There is no authentication.
GET /status¶
Health check. Returns the translation plugin name and its supported languages.
Response (JSON):
GET /detect/{utterance}¶
Detect the language of the given text.
| Path parameter | Description |
|---|---|
utterance |
The text string to classify |
Response: a language code string (e.g. "pt", "en", "fr"), returned directly from LanguageDetector.detect().
Example:
GET /classify/{utterance}¶
Return per-language confidence scores for the given text.
| Path parameter | Description |
|---|---|
utterance |
The text string to classify |
Response: a JSON object mapping language codes to confidence floats, returned from LanguageDetector.detect_probs().
Example:
GET /translate/{tgt_lang}/{utterance}¶
Translate text to the target language, auto-detecting the source language.
| Path parameter | Description |
|---|---|
tgt_lang |
Target language code (e.g. "en", "pt") |
utterance |
Text to translate |
Response: translated string, returned directly from LanguageTranslator.translate(utterance, target=lang).
Example:
GET /translate/{src_lang}/{tgt_lang}/{utterance}¶
Translate text with an explicit source language.
| Path parameter | Description |
|---|---|
src_lang |
Source language code (e.g. "pt") |
tgt_lang |
Target language code (e.g. "en") |
utterance |
Text to translate |
Response: translated string, returned from LanguageTranslator.translate(utterance, target=lang, source=src).
Example:
GET /utcp¶
Returns the UTCP (Universal Tool Calling Protocol) manual describing every HTTP endpoint. UTCP-compatible agents can use it to discover and invoke the translation tools. No extra dependency is required.
Error responses¶
Every endpoint reports failures as JSON {"error": "<ExceptionType>", "detail": "<message>"}
(0.9.1a1+):
| Status | Meaning |
|---|---|
| 400 | The request itself is wrong: an unsupported or unknown language pair (ValueError). Fix the request. |
| 503 | The translation engine or model is unavailable (RuntimeError). Transient, but retrying the same request immediately will not help. |
| 500 | Any other unexpected failure. |
Vendor-Compatible Routers¶
Beyond the native endpoints above, the app mounts drop-in compatible routers. Clients written for hosted translation APIs can talk to this server unchanged: DeepL, DeepLX, LibreTranslate, Lingva, Amazon Translate, Google Translate, and Azure Translator. See the server's /docs (OpenAPI) for their exact paths.
MCP Server¶
A Model Context Protocol endpoint exposes the translate/detect tools to MCP clients, served with
the third-party fastmcp package (fastmcp>=3,<4). It requires the mcp extra:
The mcp extra installs fastmcp, not the mcp SDK
The extra name is unchanged, but it resolves fastmcp, not the official mcp SDK — MCP SDK
2.0 removed mcp.server.fastmcp.FastMCP, so a server still importing that symbol fails to
start on the 2.x SDK. This server serves with fastmcp; a client consuming a different MCP
server (like ovos-mcp-toolbox, see Agent Tool Plugins) uses the official
mcp SDK instead.
With the extra installed and the --mcp flag passed at startup, the HTTP server mounts
MCP at /mcp on its own port (0.0.0.0:9686 by default). The flag is required — installing
the extra alone no longer auto-mounts the endpoint; --mcp without the extra logs a warning
and runs without it. A standalone MCP-only process is also available, useful for running
MCP on its own host/port without exposing the HTTP API:
python -m ovos_translate_server.mcp_server \
--tx-engine ovos-translate-plugin-nllb \
--host 127.0.0.1 \
--port 9687
The standalone process defaults to host 127.0.0.1 and port 9687, distinct from the HTTP
server's 0.0.0.0:9686. The FastMCP instance can also be embedded into an existing FastAPI app.
Either way it exposes two tools: translate(text, target_lang, source_lang=None) returns the
translated string (omit source_lang to auto-detect), and detect_language(text) returns a
BCP-47 tag. A minimal MCP client call to translate looks like:
which returns a plain-string result such as "Olá, como você está?".
How It Wraps OVOS Translation Plugins¶
start_translate_server() uses two ovos-plugin-manager loader functions:
load_tx_plugin(name): looks up theopm.lang.translateentry-point group for the named pluginload_lang_detect_plugin(name): looks up theopm.lang.detectentry-point group
Both return the plugin class. Each class is instantiated with its own config section read
from mycroft.conf via Configuration(), empty when unset:
self.tx = tx_cls(config=self._plugin_config("translation", tx_plugin))
self.detect = detect_cls(config=self._plugin_config("language_detection", detect_plugin))
The translator (engine.tx) and optional detector (engine.detect) are held on a TranslateEngineWrapper. All FastAPI route handlers use them. When no detection plugin is configured, /detect and /classify call the translator's own detect() / detect_probs().
Plugin Interface¶
Translation plugins must implement LanguageTranslator from ovos_plugin_manager.templates.language:
Detection plugins must implement LanguageDetector:
class LanguageDetector:
def detect(self, text) -> str: ... # returns language code
def detect_probs(self, text) -> dict: ... # returns {lang: confidence}
Docker¶
A minimal Dockerfile for serving a single plugin:
FROM python:3.11
RUN pip install --pre "ovos-translate-server>=0.10.0a1"
RUN pip install --pre <plugin-package>
ENTRYPOINT ovos-translate-server --tx-engine <plugin-name>
Build and run:
Upcoming — Docker Compose
A default Docker Compose setup and custom-container documentation are in progress (ovos-translate-server#33).
Gotchas¶
- All endpoints are
GETwith the text in the URL path. Long or special-character utterances must be URL-encoded by the client. There is no request body and no authentication. Don't expose this server directly to untrusted networks. Front it with a reverse proxy. - MCP mounts at
/mcpon the same HTTP server and port (9686) only when the server starts with the--mcpflag and themcpextra is installed. The extra alone does not auto-mount the endpoint. The standalone MCP-only process (python -m ovos_translate_server.mcp_server, default127.0.0.1:9687) is a separate, optional way to run MCP without the HTTP API; running one does not start the other.
Source code: OpenVoiceOS/ovos-translate-server.
Read next: Server Compatibility Layers Related: STT Server · TTS Server · Translation Plugins · Bidirectional Translation