jev
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@jevScore these three options for our roadmap: A, B, C."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
GenericJevMCP via DiffusionGemma
日本語 · Validation · Provenance
Structured yes/no, choice, and score decisions through MCP, a terminal, or HTTP. A CPU adapter reads bounded answer-token slots from a shared DiffusionGemma NVFP4 backend, returning candidate probabilities and measured elapsed time without generating an essay for each decision.
This is an experimental, self-hosted implementation of Jev-style decisions. The internal API name dg-bert is historical: no BERT model is loaded. The calling assistant is independent of the decision backend.
Architecture
MCP host / terminal → Python client → optional SSH → CPU adapter :8011
↓
DiffusionGemma / vLLM :8010Text, optional evidence, or one image can be evaluated with multiple questions in a joint read or with isolated sequential questions. Ordinary generation on port 8010 and decisions share the same loaded weights. Decisions use one diffusion step per read; ordinary generation uses the denoising schedule.
Related MCP server: mcp-confidence
Repository layout
.
├── jev/ Python API, decision logic, CLI, calibration
├── mcp/ MCP stdio server
├── scripts/ Model preparation, service lifecycle, monitoring
├── tests/ CPU and MCP tests
│ └── live/ Opt-in checks against a running GPU service
├── runtime/ Pinned vLLM overlay and build-time checks
├── examples/ Request examples
├── skills/ Optional assistant skill
└── docs/ Validation scopeRun Python entry points from the repository root: python -m jev.client, python -m jev.calibration, and python scripts/service.py. MCP sets its Python working directory to this root. Local .env, client-config.json, state/ and corpus/ remain at the root and stay untracked.
Requirements
Component | Required environment / tested scope |
GPU host | Linux ARM64, GB10, 128 GB unified memory; tested on MSI EdgeXpert (DGX Spark-class) |
Runtime | NVIDIA-enabled Docker; pinned base image and overlay, built with Dockerfile |
Weights | Exact NVIDIA DiffusionGemma 26B-A4B NVFP4 revision in models.lock.json, downloaded separately |
Python | Python 3.10+ syntax; client/CPU tests verified on 3.13; install requirements.txt |
MCP host | Node.js 20+, Python on PATH or JEV_PYTHON, and npm ci |
Remote connection | OpenSSH key authentication; APIs bind to loopback |
Provision storage for approximately 19 GB of model files, Docker layers, and runtime caches. Weights, credentials and private corpora are not distributed. Other GPU types, x86 hosts and upstream runtime versions are outside the tested deployment.
GPU server setup
Run on the Linux GPU host. Review the model card and model terms before downloading. The code license does not replace model terms.
git clone https://github.com/Bizuayeu/GenericJevMCP-via-DiffusionGemma.git
cd GenericJevMCP-via-DiffusionGemma
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
python scripts/prepare_model.py --download
# Or verify an existing snapshot:
# python scripts/prepare_model.py --snapshot /absolute/cache/path/snapshots/REVISION
python scripts/service.py init --download-status state/download-status.json
docker build -t generic-jev:local .
export JEV_IMAGE=$(docker image inspect generic-jev:local --format '{{.Id}}')
python scripts/service.py start-backend
# Wait until ready; first compilation can take longer than warm inference.
curl --fail http://127.0.0.1:8010/health
python scripts/service.py start-adapter
curl --fail http://127.0.0.1:8011/healthThe preparation command downloads the pinned revision under ~/.cache/huggingface and verifies filenames/sizes. Initialization generates local credentials with mode 0600 without replacing an existing .env. No corpus is required.
Keep JEV_IMAGE set to your built image ID for service operations and monitoring. The source default is the original tested image ID, not an image already present on your machine. The build verifies the pinned base and overlay hashes.
Optionally run python scripts/monitor.py in another terminal with the same JEV_IMAGE. It stops matching managed GPU containers when host memory falls below the configured reserve; it is not an all-allocation OOM guarantee. Neither services nor monitor are registered for OS autostart. Stop with python scripts/service.py stop-adapter / stop-backend. When settings change, stop and retain/rename the old container before recreating it: the service refuses silent configuration replacement.
Three decision types
python -m jev.client decide --question 'Does water contain hydrogen?' --format text
python -m jev.client decide --question 'Capital of Japan?' --choices Tokyo Osaka Kyoto --format text
python -m jev.client decide --request examples/three-types.jsonType | Request | Meaning |
yes/no | type: noul | noul = P(yes); probabilities contains yes/no |
choice | type: choice; criteria maps candidate names to descriptions or null | choice = highest-probability candidate; distribution over supplied candidates |
score | type: score; criteria = ordered label array | score = zero-based expected index, not necessarily an integer |
For score probabilities [0.1, 0.2, 0.7], the result is 0×0.1 + 1×0.2 + 2×0.7 = 1.6. The legend maps indices to labels. For every type, confidence is the largest candidate probability; when the answer is no, noul and confidence differ.
{
"state": "The package contains three red balls.",
"questions": {
"contains_red": {"type": "noul", "instructions": "Does it contain a red ball?"},
"color": {"type": "choice", "instructions": "What color?", "criteria": {"red": null, "blue": null}},
"explicitness": {"type": "score", "instructions": "How explicitly is the color stated?", "criteria": ["not stated", "implied", "explicit"]}
}
}State is optional: model knowledge is enabled by default. Add --state 'text', repeatable --state-file file.md, or --image photo.png. Files are read by the client and images are encoded as data URLs. A path/URL inside state is not fetched. Existing state and state-file cannot be combined. Failed reads and oversized inputs are errors, never silent truncation.
For inline JSON use --request-json '…' or UTF-8 stdin with --request-json -. PowerShell stdin preserves quotes:
$OutputEncoding = [System.Text.UTF8Encoding]::new($false)
@'
{"questions":{"answer":{"type":"noul","instructions":"Does water contain hydrogen?"}}}
'@ | python -X utf8 -m jev.client decide --request-json - --format textRemote clients
Clone the source on the client too. Use your SSH alias and the actual server checkout path:
python -m jev.client --ssh-config /path/to/ssh_config --ssh-host spark --remote-root /opt/GenericJevMCP decide --question 'Capital of Japan?' --choices Tokyo Osaka KyotoAlternatively set JEV_SSH_CONFIG, JEV_SSH_HOST, JEV_REMOTE_ROOT, or put ssh_config, ssh_host, remote_root in an ignored client-config.json in the repository root. CLI flags override environment variables, which override the file. Without an SSH config, calls are local. API keys remain on the server.
MCP setup
Run npm ci in the checkout on the MCP host. Configure your host with absolute paths:
{
"mcpServers": {
"jev": {
"command": "node",
"args": ["/absolute/path/GenericJevMCP-via-DiffusionGemma/mcp/server.mjs"],
"env": {
"JEV_PYTHON": "/absolute/path/to/python",
"JEV_SSH_CONFIG": "/absolute/path/to/ssh_config",
"JEV_SSH_HOST": "spark",
"JEV_REMOTE_ROOT": "/opt/GenericJevMCP"
},
"timeoutSeconds": 240
}
}
}Omit SSH variables on the GPU host. Host formats vary; timeoutSeconds is the tested Antigravity setting, allowing for the client's 200-second SSH timeout. The bridge starts the fixed Python client with shell:false. Tool callers cannot select an executable or change the SSH destination.
Call decide with:
{"request":{"questions":{"answer":{"type":"noul","instructions":"Does water contain hydrogen?"}}}}Optional top-level arguments are image (one local path) and state_files (UTF-8 paths). The MCP host reads them and transmits their content to the configured GPU server.
For Antigravity, register this server, copy skills/jev to ~/.gemini/antigravity-cli/skills/jev, and restart. Use /jev [AdditionalInput] <OutputCategory>. To auto-allow only this tool, add mcp(jev/decide) to permissions.allow in the host settings. No all-command permission is required. The tool description carries probability semantics instead of repeating a disclaimer in each result.
Probability calibration and abstention
Probabilities are uncalibrated and normalized within the supplied candidates, not probabilities of factual correctness. A missing best answer can still yield a confident selection. Diagnostics expose label mass, label entropy, whether the vocabulary argmax is a permitted label, and read count. If every read's argmax falls outside the labels, the answer is null.
With sources_only:true, an extra evidence-sufficiency decision nulls unsupported answers. That gate is itself a model judgment. Explicit retrieval with no match abstains without inference.
jev/calibration.py fits temperature on labeled examples and evaluates accuracy, NLL and ECE on disjoint context groups:
[{"group":"document-001","probabilities":[0.9,0.1],"correct":0}]python -m jev.calibration --fit records/fit.json --evaluate records/evaluation.jsonUse deployment-matched model, prompt, candidate order, mode and samples. Questions from one source share a group; overlapping fit/evaluation groups are rejected. Do not invent probabilities for abstentions. The upstream-derived grid is 0.2–4.0 in 0.05 steps; improvement on held-out data must be measured.
This tool is an offline evaluator, not automatic serving calibration. It does not modify the API, which retains calibrated:false. No real domain calibration dataset has been validated here; the numerical tests use synthetic distributions. This is distinct from NVFP4 quantization calibration.
Latency breakdown
Field / measurement | What it includes |
Client elapsed_seconds | Client main entry through argument/file processing and API/SSH response receipt; excludes interpreter/import startup and final rendering |
diagnostics.elapsed_seconds | Decision engine prompt/slot processing and backend HTTP reads, including repeats; excludes adapter validation, retrieval and source-only postprocessing |
Difference | Input preparation plus SSH/network and adapter overhead; not a separate input-only timer |
Full assistant turn | Also caller LLM planning, tool orchestration and final response; outside client timing |
Individual Windows→SSH→GB10 observations, 2026-09-20:
Request | Client total | Decision | Difference |
Single choice | 1.387 s | 0.120 s | 1.267 s |
Two short questions | 0.728 s | 0.127 s | 0.601 s |
Text file + choice | 11.147 s | 0.382 s | 10.765 s |
MCP yes/no | 1.698 s | 0.097 s | 1.601 s |
The MCP example's full assistant turn took 8.472 s. These are single observations, not percentiles or an optimization comparison. The slow file example does not isolate file-read cost. No-match retrieval has zero reads and can omit decision time.
Local HTTP probes: four short questions took 0.108 s joint/warm and 0.374 s separate/warm. Two-question image probes took 4.341 s on first shape use and 0.326–0.335 s warm. Compilation and concurrency matter. Evidence and limits.
One Spark-class machine: capacity and limits
Verified hardware: one GB10 system with 128 GB unified memory. These are deployed settings, not a maximum-capacity benchmark:
Setting | Value |
Backend context limit / maximum sequences | 131,072 tokens / 4 |
BF16 KV budget | 6 GiB |
Generation canvas / denoising steps | 256 / 48 |
Decision steps | 1 per read; auto uses 1 or 4 reads |
Adapter simultaneous requests | 2 |
Questions / candidates per question | 1–16 / 2–26 |
Serialized state | 32,768 characters |
Images / body | One PNG/JPEG, 4 MiB raw / 8 MiB HTTP body |
PyTorch worker memory cap | 38% of device memory |
Backend / adapter container limits | 60 GiB / 1 GiB |
Startup admission estimate: 19 GiB weights + 6 KV + 10 sampler transient + 12 host reserve = 47 GiB available. This is not measured peak consumption. The PyTorch cap does not constrain every other library allocation.
Co-residency with a separate Gemma 26B NVFP4 backend and mixed generation/decision calls were tested. Host available memory was about 43 GiB after later vision validation, not a measurement of every startup peak. Maximum-context quality, saturation throughput and long-duration stability are unverified. The 16-question/26-candidate limits are also bounded by the answer canvas and 128 unique label-token IDs: not every maximal combination is valid.
Retrieval, modes, and HTTP
The generic path needs no corpus. jev/corpus.py is a site-specific HTTrack importer, not a universal document importer. No source archive is distributed. An optional corpus/surei.jsonl can contain your own entries with id, title and text plus optional provenance. Query retrieval uses Japanese character-bigram BM25; number lookup retains the original 1–91 convention. Restart the adapter after corpus changes.
POST /v1/systemone on loopback port 8011 requires Bearer authentication. The /v1/chat/completions wrapper accepts two messages: system = schema JSON, user = state JSON. Free-form generation uses port 8010. Use SSH forwarding for remote HTTP access.
Mode joint is the default; separate processes independent question inputs sequentially with a stable seed and per-question adaptive reads. Samples auto uses four reads if initial label entropy exceeds 0.1 nats or argmax lies outside labels. Fixed samples: 1–32. Isolation and seed do not guarantee bit-identical GPU results.
Tests
pip install -r requirements.txt
# Download only the pinned tokenizer, not model shards.
python -c "import json, shutil; from huggingface_hub import hf_hub_download; m=json.load(open('models.lock.json'))['diffusion']; shutil.copyfile(hf_hub_download(m['model'],'tokenizer.json',revision=m['revision']), 'tests/tokenizer.json')"
python -m unittest discover -s tests -v
npm ci
npm testRuntime overlay checks run during Docker build. Live scripts tests/live/verify_stack.py and tests/live/verify_rag.py retain companion-model/private-corpus assumptions; they are not fresh-install acceptance tests. CPU tests and generic examples need no private corpus. See validation for the actual published verification scope.
With a running configured GPU service, npm run smoke exercises MCP initialize, tool discovery and all three decision types. It does not start the GPU backend.
License and provenance
Code: Apache-2.0. NOTICE.md credits the pinned vLLM forks, mmastrac/djev-spark, and open-alternative-jev. Model weights have their own terms, including the Gemma terms referenced by the NVIDIA model card. This is not an official Google or NVIDIA product.
Available Tools
1 tooldecideARead-only
Return yes/no (noul), choice or score decisions and elapsed seconds using DiffusionGemma. request.questions maps IDs to {type, instructions, criteria}; choice criteria map names to descriptions or null; score criteria are ordered labels. state is optional evidence; sources_only:true restricts evidence. image/state_files read local files and send them to the configured decision server. Files are not modified. Probabilities are uncalibrated and normalized within the supplied candidates, not factual correctness probabilities. Explain this when asked rather than repeating a disclaimer in every result.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | ||
| request | Yes | ||
| state_files | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false, and the description reinforces this with 'Files are not modified.' It goes beyond annotations by disclosing that local files are read and sent to a decision server, that probabilities are uncalibrated and normalized within supplied candidates rather than factual correctness, and that the assistant should explain this when asked rather than repeating disclaimers.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose is front-loaded in the first sentence, and each following sentence adds schema or behavioral detail without padding. The middle is dense and somewhat run-on, but every clause provides useful information, so it earns a high score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the essential inputs and output categories, but because there is no output schema it does not fully explain the exact result structure beyond 'decisions and elapsed seconds.' It also omits documentation for several request subfields, leaving the tool workable but not fully complete for complex calls.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at 0%, the description carries the burden and does meaningfully explain request.questions mappings, choice and score criteria structure, state, sources_only, and image/state_files. However, it leaves request.mode, request.seed, request.samples, and request.rag without any explanation, creating a notable gap for an agent trying to use all options correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Return yes/no (noul), choice or score decisions and elapsed seconds using DiffusionGemma.' It clearly identifies what the tool produces and distinguishes the decision types, making the purpose unmistakable even without a title.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides conditional usage cues such as 'state is optional evidence' and 'sources_only:true restricts evidence,' and explains when image/state_files are relevant. However, there is no explicit statement of when to prefer this tool over alternatives or when not to use it, and no sibling tools are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.1.0- First observed
decide
TDQS
Scored across 1 tool
Only one tool exists, so there is no possibility of confusing it with another tool. The tool's single responsibility is clear from its description.
With only one tool, there are no naming inconsistencies to evaluate. The name 'decide' is a simple, verb-based descriptor matching its function.
A single tool feels thin for a server, even though it supports multiple decision types internally. This falls at the low end of the borderline range.
The tool covers yes/no, choice, and score decisions, with evidence and file handling. Minor gaps include lack of server configuration or status inspection, but core decision functionality is well covered.
Maintenance
Related MCP Connectors
AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.
MCP server for visual regression testing: triage a PR's UI diffs from your coding agent.
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
Human-input bridge for AI agents with voice-first answer links, MCP tools, and HTTP APIs.
Related MCP Servers
- AlicenseAqualityFmaintenanceProduction-grade MCP server for image and video understanding and generation across Gemini, OpenAI, and Grok.5564 PyPI4Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables LLM agents to route responses as accept, verify, or ask-a-human based on token logprobs, and provides an MCP server for delegating generation to local models with confidence bands.MIT
- AlicenseAqualityDmaintenanceA local, open-source MCP server that provides deterministic organizational tools for structured decisions, guided reflection, action planning, and transparent digital report outlines without requiring an API key.628 npmMIT
- AlicenseNot gradedqualityDmaintenanceLocal-first MCP server for controlling a loopback ComfyUI instance from same-machine or authenticated LAN clients.MIT