The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Xcomet MCP Server listing page.
⚠️ This is an unofficial community project, not affiliated with Unbabel.
Translation quality evaluation MCP Server powered by xCOMET (eXplainable COMET).
xCOMET MCP Server provides AI agents with the ability to evaluate machine translation quality. It integrates with the xCOMET model from Unbabel to provide:
xCOMET requires Python with several packages. We recommend using a virtual environment:
Why Python 3.9-3.12?
unbabel-cometdeclaresnumpy = "^1.20.0", so it resolves numpy 1.x. The last numpy 1.x release, 1.26.4, ships wheels for cp39-cp312 only. On Python 3.13 or later, pip has to build numpy from source.
Note (v0.5.0+): The Python worker now talks to Node.js over stdin/stdout (line-delimited JSON-RPC). FastAPI, uvicorn, and pydantic are no longer required — only
unbabel-cometis.
Note: When using with Claude Desktop or other MCP hosts, set
XCOMET_PYTHON_PATHto point to the venv Python (see Configuration).
Important: XCOMET-XL and XCOMET-XXL are gated models on HuggingFace. You must:
Create a HuggingFace account
Visit Unbabel/XCOMET-XL and request access
Authenticate, either via the CLI:
(
huggingface-cli loginstill works but prints a deprecation warning since huggingface_hub 0.34;hfis the current command.)Or by setting
HF_TOKENin the MCP host'senvblock, which is the option when the host launches the server in an environment where no CLI login has been performed:huggingface_hub reads
HF_TOKENfirst and falls back to the token file written byhf auth login.
Unbabel/wmt22-comet-dadoes not require authentication (but requires reference translations).
After authentication, download the model (~14GB for XL, ~42GB for XXL):
Not in the virtualenv. The venv holds the Python packages; the model weights go to the huggingface_hub cache, which is a separate directory shared by every tool on the machine that pulls from the Hub.
download_model() passes cache_dir=None to snapshot_download(), so
huggingface_hub picks the location: HF_HUB_CACHE, which defaults to
HF_HOME/hub, where HF_HOME defaults to $XDG_CACHE_HOME/huggingface
(~/.cache/huggingface when XDG_CACHE_HOME is unset).
Three consequences worth knowing:
hf cache scan to see what is actually on disk, and hf cache delete to
remove a revision.To put the checkpoint somewhere else — a larger volume, a shared drive — set
XCOMET_SAVING_DIRECTORY (v0.7.0+) or the standard HF_HOME. Both are read at
download time, so a model already downloaded to the default location is not
moved; it is downloaded again into the new one.
engines.node in package.json; CI runs on 22 and 24)Note: If you just want to use xCOMET MCP Server, you do not need to clone this repository. Install the Python environment and model (see Prerequisites), then use
npx(see Usage). The section below is for contributors and local development only.
For contributors and local development:
Add to your Claude Desktop configuration (claude_desktop_config.json):
Tip: If you installed Python packages system-wide or use pyenv,
XCOMET_PYTHON_PATHmay be omitted (auto-detection will find it). See Python Path Auto-Detection for details.
If you prefer installing globally:
Then configure:
If you cloned and built the repository locally (see Installation):
xcomet_evaluateEvaluate translation quality for a single source-translation pair.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
source | string | ✅ | Original source text |
translation | string | ✅ | Translated text to evaluate |
reference | string | ❌ | Reference translation |
source_lang | string | ❌ | Source language code (ISO 639-1) |
target_lang | string | ❌ | Target language code (ISO 639-1) |
response_format | "json" | "markdown" | ❌ | Output format (default: "json") |
use_gpu | boolean | ❌ | Use GPU for inference (default: false) |
Example:
Response:
xcomet_detect_errorsFocus on detecting and categorizing translation errors.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
source | string | ✅ | Original source text |
translation | string | ✅ | Translated text to analyze |
reference | string | ❌ | Reference translation |
min_severity | "minor" | "major" | "critical" | ❌ | Minimum severity (default: "minor") |
response_format | "json" | "markdown" | ❌ | Output format |
use_gpu | boolean | ❌ | Use GPU for inference (default: false) |
xcomet_batch_evaluateEvaluate multiple translation pairs in a single request.
Performance Note: With the persistent server architecture (v0.3.0+), the model stays loaded in memory. Batch evaluation processes all pairs efficiently without reloading the model.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
pairs | array | ✅ | Array of {source, translation, reference?} (max 500) |
source_lang | string | ❌ | Source language code |
target_lang | string | ❌ | Target language code |
response_format | "json" | "markdown" | ❌ | Output format |
use_gpu | boolean | ❌ | Use GPU for inference (default: false) |
batch_size | number | ❌ | Batch size 1-64 (default: 8). Larger = faster but uses more memory |
Example:
xCOMET MCP Server is designed to work alongside other MCP servers for complete translation workflows:
Configure both servers in Claude Desktop:
Then ask Claude:
"Translate this text to Japanese using DeepL, then evaluate the translation quality with xCOMET. If the score is below 0.8, suggest improvements."
| Variable | Default | Description |
|---|---|---|
XCOMET_MODEL | Unbabel/XCOMET-XL | xCOMET model to use |
XCOMET_PYTHON_PATH | (auto-detect) | Python executable path (see below) |
XCOMET_PRELOAD | false | Pre-load model at startup (v0.3.1+) |
XCOMET_DEBUG | false | Enable verbose debug logging (v0.3.1+) |
XCOMET_NUM_WORKERS | 1 | DataLoader workers for model.predict() (v0.6.0+). Increase to better utilize idle CPU cores when running large batches, especially on GPU. Invalid values silently fall back to 1. |
XCOMET_SAVING_DIRECTORY | (HuggingFace cache) | Directory to download the checkpoint into (v0.7.0+). Unset, the model goes to the huggingface_hub cache (HF_HOME, default ~/.cache/huggingface). Set this to put a 14GB (XL) or 43GB (XXL) checkpoint on another volume. |
XCOMET_LOCAL_FILES_ONLY | false | Resolve the checkpoint from the local cache only (v0.7.0+). Set to true to start with no network access; the model must already be downloaded. |
HF_TOKEN | (unset) | HuggingFace access token, read by huggingface_hub. An alternative to hf auth login for the gated models (XCOMET-XL, XCOMET-XXL, the CometKiwi models). |
Choose the model based on your quality/performance needs:
| Model | Parameters | Size | Memory | Reference | HF Auth | Quality | Use Case |
|---|---|---|---|---|---|---|---|
Unbabel/XCOMET-XL | 3.5B | ~14GB | ~8-10GB | Optional | ✅ Required | ⭐⭐⭐⭐ | Recommended for most use cases |
Unbabel/XCOMET-XXL | 10.7B | ~42GB | ~20GB | Optional | ✅ Required | ⭐⭐⭐⭐⭐ | Highest quality, requires more resources |
Unbabel/wmt22-comet-da | 580M | ~2GB | ~3GB | Required | Not required | ⭐⭐⭐ | Lightweight, faster loading |
Important: XCOMET-XL and XCOMET-XXL are gated models on HuggingFace. Each model requires separate access approval. See Model Download for authentication setup.
Important:
wmt22-comet-darequires areferencetranslation for evaluation. XCOMET models support referenceless evaluation.
Tip: If you experience memory issues or slow model loading, try
Unbabel/wmt22-comet-dafor faster performance with slightly lower accuracy (but remember to provide reference translations).
To use a different model, set the XCOMET_MODEL environment variable:
The server automatically detects a Python environment with unbabel-comet installed:
XCOMET_PYTHON_PATH environment variable (if set)~/.pyenv/versions/*/bin/python3) - checks for comet module/opt/homebrew/bin/python3, /usr/local/bin/python3)python3 commandThis ensures the server works correctly even when the MCP host (e.g., Claude Desktop) uses a different Python than your terminal.
Example: Explicit Python path configuration
The server uses a persistent Python worker process that keeps the xCOMET model loaded in memory. The Node.js MCP server talks to the worker over stdin/stdout using a line-delimited JSON-RPC protocol — no local HTTP listener, no port binding, no FastAPI.
| Request | Time | Notes |
|---|---|---|
| First request | ~25-90s | Model loading (varies by model size) |
| Subsequent requests | ~500ms | Model already loaded |
This provides a 177x speedup for consecutive evaluations compared to reloading the model each time.
Enable XCOMET_PRELOAD=true to pre-load the model at server startup:
With preload enabled, all requests are fast (~500ms), including the first one.
The xcomet_batch_evaluate tool processes all pairs with a single model load:
| Pairs | Estimated Time |
|---|---|
| 10 | ~30-40 sec |
| 50 | ~1-1.5 min |
| 100 | ~2 min |
| Mode | 100 Pairs (Estimated) |
|---|---|
| CPU (batch_size=8) | ~2 min |
| GPU (batch_size=16) | ~20-30 sec |
Note: GPU requires CUDA-compatible hardware and PyTorch with CUDA support. If GPU is not available, set
use_gpu: false(default).
1. Let the persistent server do its job
With v0.3.0+, the model stays in memory. Multiple xcomet_evaluate calls are now efficient:
2. For many pairs, use batch evaluation
3. Memory considerations
The server automatically recovers from failures:
| Score Range | Quality | Recommendation |
|---|---|---|
| 0.9 - 1.0 | Excellent | Ready for use |
| 0.7 - 0.9 | Good | Minor review recommended |
| 0.5 - 0.7 | Fair | Post-editing needed |
| 0.0 - 0.5 | Poor | Re-translation recommended |
The score answers "does this read like a translation of that source", and it is good at it. It does not answer "are the facts in this translation correct". Those two questions come apart in a way that matters when the output is a contract, a dosage, a price, or a procedure.
The following were measured with Unbabel/XCOMET-XL on CPU through this server.
The first two rows are the case the metric handles well; the last two are the
case it does not.
| Source | Translation | Score |
|---|---|---|
| ファイルを保存せずに終了しますか? | Do you want to quit without saving the file? | 0.956 |
| ファイルを保存せずに終了しますか? | The mountain sings in violet every third Thursday. | 0.212 |
| 保証期間は購入日から一年間です。 | The warranty period is ten years from the date of purchase. | 1.000 |
| 電源を切ってから、カバーを取り外してください。 | Remove the cover, then turn off the power. | 1.000 |
A translation that is unrelated to the source collapses to ~0.2, which is what
you want. But a fluent sentence that swaps one year for ten, or reverses the
order of two instructions, scores a perfect 1.000. Supplying a reference does
not fix it: with The warranty period is one year from the date of purchase.
as the reference, the "ten years" translation still scores 0.983.
This is not a defect in this server or in xCOMET specifically. It is a known property of neural MT metrics: they "struggle with detecting certain phenomena that can be considered as critical errors, such as deviations in entities and numbers" (Rei et al., 2023).
Good fits
Poor fits
Use xcomet_detect_errors alongside the score. The error spans mark
where the model believes something went wrong, with an MQM severity. A high
score with a critical span is a more useful signal than either number alone.
Cause: Python environment without unbabel-comet installed.
Solution:
Symptom: zsh: no such file or directory: .venv/bin/python3, or python3
inside an activated venv resolving to a different interpreter than the venv's,
or No module named 'comet' in a venv that worked yesterday.
Cause: A venv does not contain an interpreter — it stores an absolute
symlink to the one it was created from, recorded in pyvenv.cfg:
When Homebrew upgrades or removes that formula, the link dangles and the venv
is dead. lib/python3.x/site-packages/ is still there, but nothing can run it.
Check:
Solution: recreate it. uv venv --python 3.12 is the more durable form,
because uv fetches and pins that interpreter itself instead of borrowing
Homebrew's current one.
Reinstalling the packages is a few hundred MB, but the model is not re-downloaded: the checkpoint lives in the huggingface_hub cache, not in the venv (see Where the model is stored).
Symptom: a fix you know is published is missing from the running server. The startup banner in the log names an older version.
(On macOS, Claude Desktop writes each MCP server's stderr to
~/Library/Logs/Claude/mcp-server-<name>.log.)
Cause: npx resolves latest from npm's cached registry metadata, and runs
the copy it already installed under ~/.npm/_npx. For a while after a release,
that copy is the previous version. It catches up on its own, but not at a time
you choose. @latest does not change this — to npm it means the same as writing
no version at all.
Solution: clear the npx cache, then restart the MCP host.
ps shows which copy is running, and which cache directory it came from.
To stay on a known build, pin an exact version: xcomet-mcp-server@0.7.0.
Cause: Large model files (~14GB for XL) require stable internet connection. XCOMET models also require HuggingFace authentication (see Model Download).
Solution:
If the download was interrupted, the cache keeps a snapshot directory with no
checkpoints/model.ckpt in it. The server reports that path and asks you to
delete the directory; hf cache scan lists where it is.
Cause: PyTorch not installed with CUDA support.
Solution:
Cause: Mac MPS (Metal Performance Shaders) has compatibility issues with some operations.
Solution: The server automatically uses num_workers=1 for Mac MPS compatibility. For best performance on Mac, use CPU mode (use_gpu: false).
Cause: XCOMET-XL requires ~8-10GB RAM.
Solutions:
XCOMET_MODEL=Unbabel/wmt22-comet-da for lower memory usage (~3GB)Cause: High memory usage from the xCOMET model (~8-10GB for XL).
Solution:
XCOMET_MODEL=Unbabel/wmt22-comet-daIf you encounter issues:
XCOMET_DEBUG=true)npm run test:python calls python3 -m pytest, so pytest has to be importable from
whichever python3 is on your PATH. Activating the xCOMET venv does not help unless
pytest is installed in it. Any of these work:
tests/README.md documents every suite, what it covers, and why.
See CHANGELOG.md for version history and updates.
MIT License - see LICENSE for details.