MCP Server for Laya
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
MCP Server for Laya
An MCP server that exposes Laya — a non-autoregressive "System 1" decision model — to MCP clients (Claude Desktop, Claude Code, Codex CLI, VS Code Copilot, Cursor, and compatible hosts).
Give it a text and a typed question; it answers in a single forward pass, with probabilities. No text generation, no prompt, no output parsing.
Features
Typed decisions over text: choice between options, yes/no, and ordinal score
100+ languages (multilingual checkpoint)
Local inference on CPU through
laya-tsand ONNX Runtime — no Python at runtime and no inference API: the text is processed in-process (see the telemetry note in Security Notes)Several questions about the same text in one call
stdio and Streamable HTTP transports
Typical uses: ticket/email routing, intent and category classification, triage, moderation, yes/no checks over text.
Related MCP server: laya-mcp
Available Tools
Tool | Description |
| Picks exactly one of N options (2–100, ideally < 20); returns the choice and every option's probability |
| Yes/no check phrased as a statement; returns the probability that it is true |
| Ordinal scale you define (2–10 levels); returns expected level and per-level probabilities. Weakest type — prefer |
| Several choice/score/yes-no questions about the same text in one call (cheaper than separate calls) |
| Model directory, load state, token limits and the calibration caveat |
Options of a choice may be plain strings or { "key": "...", "description": "..." } — descriptions improve accuracy.
Example (laya_choice):
{
"text": "O produto chegou quebrado e ninguém me responde há uma semana.",
"question": "Qual setor deve responder?",
"options": [
{ "key": "logística", "description": "entrega e avarias" },
{ "key": "financeiro", "description": "cobranças" },
"suporte"
]
}{
"type": "choice",
"choice": "logística",
"probabilities": { "logística": 0.8821, "financeiro": 0.0007, "suporte": 0.1172 },
"confidence": 0.8821,
"usage": { "truncated": false, "stateTokens": 13, "droppedTokens": 0 }
}If the text exceeds the model's token budget (about 1,024 tokens), usage.truncated is true and a warning is returned.
Know the limits
These come from the checkpoint itself (see its model card) and from manual tests; the MCP surfaces them rather than hiding them:
Probabilities are uncalibrated (temperature 1.0) and over-confident. Use them to rank options or to set a review threshold validated on your own data (for example, send to a human when the top probability is below ~0.6), not as true likelihoods.
noulcan under-report "true", and wording matters. In a quick test, "Does the customer show interest in buying?" scored 0.10 on a clear price inquiry, while the declarative "The customer asks about prices." scored 0.92. Phrasenoulas a short statement about the text and treat values near 0.5 as inconclusive.scoreis the weakest decision type and has a measured bias against the first level: a text saying "no rush" was rated "critical" (62%) with only 2% on the lowest level. For urgency, sentiment and similar scales, preferlaya_choicewith named levels (e.g.urgent/can wait), which got both test cases right. The fractionalscoreis still usable as a relative ranking.A choice returns one option only: a text with two topics (e.g. an access problem and a strange invoice) gets a single, often very confident, label.
Keep choices under ~20 options. The server accepts up to 100 but warns above 20.
Low-resource languages (e.g. Swahili, Tamil, Amharic) are weak.
The observations above come from a handful of manual tests, not a benchmark. Validate on labelled data of your own before relying on any threshold.
Requirements
Node.js 18+
The ONNX export of a Laya checkpoint (one-time preparation, next section)
~1.3 GB of disk for the multilingual ONNX export. Cold load takes ~5 s; a 3-question prediction takes ~0.6 s on CPU.
Preparing the model
laya-ts does not read the Hugging Face model.safetensors directly; it needs a split ONNX export (encoder.onnx + head.onnx). Do this once per checkpoint. Python is needed only for this step, not at runtime.
Use the multilingual checkpoint for anything that is not English. The English one (root of
convaiinnovations/laya) collapses outside English while staying confident.
Bash (Linux/macOS/WSL):
# 1. Get the Laya repository (it contains the export script and the Python package)
git clone --depth 1 https://github.com/NandhaKishorM/laya ~/laya-src
# 2. Python environment (outside this repo; CPU torch is enough)
python3 -m venv ~/venvs/laya-export
source ~/venvs/laya-export/bin/activate
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install "numpy<2.4" transformers huggingface_hub onnx onnxruntime onnxscript safetensors
pip install --no-deps ~/laya-src
# 3. Export (downloads the weights from Hugging Face by itself, ~650 MB)
USE_TF=0 python ~/laya-src/laya-ts/scripts/export_onnx.py \
--repo convaiinnovations/laya --subfolder multilingual \
--out-dir ~/models/laya-onnx/multilingualPowerShell:
git clone --depth 1 https://github.com/NandhaKishorM/laya $HOME\laya-src
python -m venv $HOME\venvs\laya-export
& $HOME\venvs\laya-export\Scripts\Activate.ps1
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install "numpy<2.4" transformers huggingface_hub onnx onnxruntime onnxscript safetensors
pip install --no-deps $HOME\laya-src
$env:USE_TF = "0"
python $HOME\laya-src\laya-ts\scripts\export_onnx.py `
--repo convaiinnovations/laya --subfolder multilingual `
--out-dir C:\models\laya-onnx\multilingualThe script verifies that PyTorch and ONNX outputs match (within 1e-4) before writing anything. The result is a directory with:
encoder.onnx encoder.onnx.data head.onnx head.onnx.data
tokenizer.json rl_agent_config.jsonPoint LAYA_MODEL_DIR at that directory.
Already cloned the Hugging Face repository? Use --model-dir <path to the multilingual/ folder> instead of --repo ... --subfolder .... Beware: without a working git-lfs, model.safetensors is a ~134-byte text pointer, not the weights — run git lfs pull, or just let --repo download it.
Configuration
Variable | Required | Default | Description |
| Yes | — | Directory with the ONNX export (see above). Validated at startup |
| No | runtime default | ONNX Runtime CPU threads |
| No |
| Load the model at startup instead of on the first call |
| No |
| Transport mode: |
| No |
| HTTP server port (only used when |
| No |
| HTTP server bind address (only used when |
The model is loaded lazily on the first call (unless LAYA_PRELOAD=true) and shared by all requests; predictions run one at a time.
Usage
Run directly from GitHub
LAYA_MODEL_DIR=~/models/laya-onnx/multilingual npx github:ferronicardoso/mcp-layaWhy
ONNXRUNTIME_NODE_INSTALL=skip? On its first installnpxruns thepostinstallofonnxruntime-node, which downloads ~280 MB of CUDA libraries that this CPU-only server never uses. On a cold cache that pushes the first start past the 30 s connection timeout of MCP clients (measured: ~33 s without it, ~15 s with it). The variable only matters while the package is being installed; later starts take ~2 s.
Claude Code (CLI)
claude mcp add laya --scope user -- npx -y github:ferronicardoso/mcp-laya--scope controls where the server registration is stored:
Scope | Stored in | Visible to |
| project-local, untracked | only you, only in this project |
|
| anyone who clones the repo (commit it to share) |
| your global Claude Code config | you, across every project |
The model directory is passed with an --env flag before the --:
Bash (Linux/macOS/WSL):
claude mcp add laya --scope user \
--env LAYA_MODEL_DIR=/home/you/models/laya-onnx/multilingual \
--env ONNXRUNTIME_NODE_INSTALL=skip \
-- npx -y github:ferronicardoso/mcp-layaPowerShell:
claude mcp add laya --scope user `
--env LAYA_MODEL_DIR=C:\models\laya-onnx\multilingual `
--env ONNXRUNTIME_NODE_INSTALL=skip `
-- npx -y github:ferronicardoso/mcp-layaTo use a local clone instead of npx (see Local Development), replace the command after -- with node /path/to/mcp-laya/dist/index.js.
Codex CLI
Bash (Linux/macOS/WSL):
codex mcp add laya \
--env LAYA_MODEL_DIR=/home/you/models/laya-onnx/multilingual \
--env ONNXRUNTIME_NODE_INSTALL=skip \
npx -- -y github:ferronicardoso/mcp-layaPowerShell:
codex mcp add laya `
--env LAYA_MODEL_DIR=C:\models\laya-onnx\multilingual `
--env ONNXRUNTIME_NODE_INSTALL=skip `
npx -- -y github:ferronicardoso/mcp-layaThis registers the server in ~/.codex/config.toml. To remove it, run codex mcp remove laya.
Claude Desktop configuration
%APPDATA%\Claude\claude_desktop_config.json:
{
"mcpServers": {
"laya": {
"command": "npx",
"args": ["github:ferronicardoso/mcp-laya"],
"env": {
"LAYA_MODEL_DIR": "C:\\models\\laya-onnx\\multilingual",
"ONNXRUNTIME_NODE_INSTALL": "skip"
}
}
}
}VS Code MCP configuration
.vscode/mcp.json:
{
"servers": {
"laya": {
"command": "npx",
"args": ["github:ferronicardoso/mcp-laya"],
"env": {
"LAYA_MODEL_DIR": "/home/you/models/laya-onnx/multilingual",
"ONNXRUNTIME_NODE_INSTALL": "skip"
}
}
}
}Run with Docker (HTTP transport)
The image runs in Streamable HTTP mode by default, for use as a remote MCP endpoint (e.g. from n8n's MCP Client Tool node or any Streamable HTTP-compatible client). It is Debian-based (ONNX Runtime ships no musl/alpine binaries) and does not contain the model: mount the ONNX export as a volume, and LAYA_MODEL_DIR must point to the path inside the container (the image already defaults it to /models).
Bash (Linux/macOS/WSL):
docker run -d --name mcp-laya \
-p 3005:3005 \
-v ~/models/laya-onnx/multilingual:/models:ro \
ghcr.io/ferronicardoso/mcp-laya:latestPowerShell:
docker run -d --name mcp-laya `
-p 3005:3005 `
-v "C:\models\laya-onnx\multilingual:/models:ro" `
ghcr.io/ferronicardoso/mcp-laya:latestThe MCP endpoint is then available at http://localhost:3005/mcp. To register it:
claude mcp add --transport http laya http://localhost:3005/mcpThe container runs as the non-root node user (uid 1000), so the mounted model files must be readable by it. The image is ~430 MB: it is CPU-only and drops the GPU/other-OS binaries that onnxruntime-node bundles. It also ships no CA certificates, which (incidentally) keeps the ONNX Runtime telemetry module from uploading — see Security Notes before adding ca-certificates.
To build the image locally instead, run docker build -t mcp-laya . in the repository root and use mcp-laya as the image name above.
Local Development
git clone https://github.com/ferronicardoso/mcp-laya
cd mcp-laya
npm install
npm run buildStart the compiled server:
Bash (Linux/macOS/WSL):
LAYA_MODEL_DIR=~/models/laya-onnx/multilingual npm startPowerShell:
$env:LAYA_MODEL_DIR = "C:\models\laya-onnx\multilingual"
npm startRun the tests (the integration test with the real model runs only when LAYA_MODEL_DIR is set):
npm testsrc/
├── index.ts # MCP server, tool schemas, stdio/HTTP bootstrap
├── config.ts # env validation
├── engine.ts # lazy model loading + serialized predictions (laya-ts)
├── handlers.ts # tool logic and output formatting
├── questions.ts # input validation -> Laya question definitions
└── toolResult.ts
vendor/laya-ts/ # compiled laya-ts (see below)About vendor/laya-ts
laya-ts is not published on npm, so its compiled build (Laya repository commit b8a0f09, laya-ts 0.1.0, Apache-2.0) is vendored in vendor/laya-ts/ and imported by relative path from src/engine.ts. It is deliberately not an npm dependency: a file: dependency cannot be resolved when the package itself is installed from GitHub (npx github:...). Its only runtime dependency, onnxruntime-node, is declared in this project's package.json.
To update it:
git clone --depth 1 https://github.com/NandhaKishorM/laya /tmp/laya-src
cd /tmp/laya-src/laya-ts && npm ci && npm run build && npm pack
rm -rf /path/to/mcp-laya/vendor/laya-ts && mkdir -p /path/to/mcp-laya/vendor/laya-ts
tar -xzf laya-ts-*.tgz -C /path/to/mcp-laya/vendor/laya-ts --strip-components=1 --exclude=package/README.md --exclude=package/scriptsIf laya-ts is published to npm in the future, add it as a regular dependency, change the import in src/engine.ts and drop vendor/.
Build and Commit Workflow
This repository intentionally tracks dist/ to support npx github:user/repo usage.
The project uses a Husky pre-commit hook (install it with npm run hooks:install) to:
build TypeScript (
npm run build)stage generated artifacts (
git add dist)
Manual fallback:
npm run build
git add distTroubleshooting
Symptom | Cause / fix |
| The directory is not the ONNX export (e.g. it is the raw Hugging Face download). Run the export in Preparing the model |
Export fails or weights look empty; |
|
Client shows | Run the server by hand to see the startup error: |
| First |
First call takes a few seconds | The model loads lazily on the first call (~5 s). Set |
Answer comes with a truncation warning | The text exceeds the model's token budget; only the beginning was evaluated. Split the text or shorten it |
Security Notes
LAYA_MODEL_DIRmust point to a real directory with the ONNX export — the server refuses to start otherwise. Model files are never committed to this repository.Texts are processed in-process by the ONNX model; this server's own code makes no network calls. Telemetry caveat: the ONNX Runtime native library bundled with
onnxruntime-nodecontains a Microsoft telemetry module (OneDsTelemetry, endpointmobile.events.data.microsoft.com) that cannot be switched off from JavaScript. Whether it sends anything in your environment, and exactly what, has not been verified here (in the Docker image it logs that uploads are unavailable because the image has no CA bundle). If this matters for your data, run the server without outbound network access, or block that host (e.g.docker run --add-host mobile.events.data.microsoft.com:127.0.0.1 ..., or an/etc/hostsentry).The HTTP transport has no authentication and binds to
0.0.0.0by default. Bind to127.0.0.1(MCP_HTTP_HOST) or put it behind a reverse proxy with authentication before exposing it beyond your machine.Inputs are validated before reaching the model (text up to 200,000 characters, up to 20 questions per call, 2–100 options per choice).
Probabilities are uncalibrated; do not use them as the only basis for automated actions with real consequences (see Know the limits).
License
MIT © Raphael Augusto Ferroni Cardoso
laya-ts and Laya are Apache-2.0; the checkpoints have their own terms on the Hugging Face model page.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.
Free OpenAI-compatible inference with signed provenance receipts and 3 focused MCP tools.
A paid remote MCP for ZeroLang, built to return verdicts, receipts, usage logs, and audit-ready JSON
A paid remote MCP for HyperFrames, built to return verdicts, receipts, usage logs, and audit-ready J
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceAn MCP server that exposes eleven typed decision tools—check, choose, score, judge, route, triage, guard, grep, rank, compact, and ask—so agents can make fast, branchable yes/no, option-pick, score, and filtering decisions on text via TypeSafe's Jev model.7 npm2MIT
- AlicenseAqualityBmaintenanceEnables MCP clients to run fast, local, non-autoregressive System-1 decisions on text, including classification, triage, routing, and safety gating, via six typed tools with probabilistic outputs.8Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables local typed decision-making over MCP Streamable HTTP, running Laya and Von models to turn arbitrary state into choice, score, and yes/no answers with probabilities.3Do What The F*ck You Want To Public
- AlicenseNot gradedqualityAmaintenanceEnables agents and services to ask small decision models typed questions about text, JSON, images, or video, returning labels, scores, or yes/no answers over MCP tools or a Jev-compatible HTTP API.Apache 2.0