mcp_jev
mcp_jev is a local MCP server that runs TypeSafe Jev's fast, typed judgment calls (Choice / Noul / Score) for agents — not chat or essays.
list_packs — view the closed catalog of available judgment packs (e.g.
pr_audit,review_diff,code_audit,skill_router,command_risk,model_router,computer_use_step,i18n_copy).describe_pack — get a pack's state schema, typed questions, example state, and suggested workflow before running it.
run_pack — run a specific pack against your structured state and receive typed answers (choice/noul/score), probabilities/confidence, and usage.
run_questions — when no pack fits exactly, run your own closed, typed custom questions on custom state (same System One path).
ping — health check: server/SDK versions, pack count, and whether the TypeSafe API key is configured (without exposing the key).
Key-once setup — the TypeSafe API key is stored in
~/.mcp_jev/.env; host MCP configs stay keyless and point to a local wrapper binary.No side effects — the server only returns judgments; orchestration, gates, and actions stay in your code.
No free-form ask tool — there is deliberately no
ask_jev; all judgments are closed-catalog Choice / Noul / Score.CLI support —
doctor,smoke,scan(repo auditing viacode_audit), host config printing/writing, and key/status management.Verification tooling — mocked tests and smoke scripts let you validate packs without a live TypeSafe key.
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., "@mcp_jevScore the urgency of this ticket"
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.
mcp_jev
Local MCP server that runs TypeSafe Jev (System One) packs — typed Choice / Noul / Score judgments, not chat. When no pack fits, run_questions is the typed custom path (still System One, still not an essay).
Anyone runs it on their own PC with their own TypeSafe API key. This repo does not host Jev, proxy your key, or invent a free-form ask_jev tool.
Configure the TypeSafe key once during MCP install (~/.mcp_jev/.env). Any agent that attaches this MCP reuses it. Do not paste the key into host mcp.json / TOML.
Docs (source of truth): this repo — https://github.com/pedroknigge/mcp_jev · TypeSafe API: docs.typesafe.ai · llms.txt
Skill: skills/mcp_jev/SKILL.md · Custom judgments: docs/CUSTOM_JUDGMENTS.md · Blind dogfood: docs/DOGFOOD.md · Product backlog: docs/BACKLOG.md · Host deep dive: docs/INSTALL_AGENTS.md · Releases: docs/RELEASES.md
Why mcp_jev
mcp_jev is the judgment layer for agents and harnesses. Jev is fast at typed decisions (one Choice, a few Nouls, a Score) over a short named state. It is not a chat model and not an executor.
Use it when the host already has structured state and needs a closed-catalog call:
Layer | Owns |
Harness / agent | Observation, tools, typed strings, merges, comments, stop rules |
mcp_jev | Versioned packs or typed custom questions → |
Host config | Keyless |
Closed tools only: list_packs / describe_pack / run_pack / run_questions / ping. Key-once in ~/.mcp_jev. Patterns here follow common ecosystem loops (computer-use, review pipelines, model routing) reimplemented as packs — no copied code, no third-party trademarks. Packs are shortcuts: if one fits, run_pack. If none fits, build closed state + typed Choice / Noul / Score and call run_questions.
Jev (System One) | Chat LLM | |
Input | State + closed questions | Prompt / conversation |
Output |
| Prose you must parse |
Control | Your code composes answers | The model narrates a plan |
This MCP | Runs a pack or typed | Out of scope |
JavaScript SDK (what this server calls):
import { choice, noul, score, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient(); // reads TYPESAFE_API_KEY
await client.systemOne({
state: { /* pack state */ },
questions: {
intent: choice("…", { faq: "…", action: "…" }),
jailbreak: noul("…"),
urgency: score("…", ["routine", "soon", "emergency"]),
},
model: "jev-latest",
});Python exists (typesafe-sdk, client.system_one) if you are writing app code. This server is TypeScript / Node 20+.
Related MCP server: Jev MCP
Install (happy path)
Prerequisites: Node.js 20+, git, a TypeSafe key from console.typesafe.ai.
# macOS / Linux — checkout ~/mcp_jev; key + wrapper in ~/.mcp_jev (override: MCP_JEV_HOME)
git clone https://github.com/pedroknigge/mcp_jev.git ~/mcp_jev
~/mcp_jev/scripts/install.sh# Windows
git clone https://github.com/pedroknigge/mcp_jev.git $HOME\mcp_jev
$HOME\mcp_jev\scripts\install.ps1Already cloned? Run ./scripts/install.sh from that checkout. MCP_JEV_HOME overrides the config dir (~/.mcp_jev). Optional MCP_JEV_CHECKOUT overrides the git checkout.
The script: clones or pulls → npm install && npm run build → writes ~/.mcp_jev/bin/mcp_jev → stores TYPESAFE_API_KEY once in ~/.mcp_jev/.env (chmod 600) → prints keyless snippets for Cursor, Claude Desktop, Claude Code, Codex, Grok, and Antigravity.
Non-interactive and no key → writes ~/.mcp_jev/NOT_READY, prints a loud next step, exits non-zero. mcp_jev doctor fails until mcp_jev config set-key. Do not treat a missing key as a successful install.
Optional host write: MCP_JEV_WRITE_HOSTS=all ./scripts/install.sh (or cursor,claude_desktop,claude_code,codex,grok,antigravity). Merge is additive; existing servers stay.
Paste this keyless block (the script prints your real wrapper path):
{
"mcpServers": {
"mcp_jev": {
"command": "/Users/YOU/.mcp_jev/bin/mcp_jev"
}
}
}Then mcp_jev doctor → restart the host → ping → list_packs.
Non-interactive key: TYPESAFE_API_KEY=… ./scripts/install.sh
Later: node ~/mcp_jev/dist/index.js config set-key
Alternatives
Style | When |
Install script (prefer this) | Humans and agents. Key once, keyless host config. |
Git clone + manual build |
|
| No clone. Slow first start. Still run |
npm registry ( | Not used. This project is not published to npm. Install from GitHub; update with |
npm test mocks TypeSafe and must pass without a live key.
First-run
mcp_jev doctor # checkout, dist, wrapper, api_key_set (boolean), host registration
# or: node ~/mcp_jev/dist/index.js doctor --json
mcp_jev smoke # stdio JSON-RPC: initialize, tools/list, ping, list_packs
~/mcp_jev/scripts/verify-mcp.sh # same smoke as a script
npm run smoke:packs # ping → list_packs → describe+run every pack (mocked TypeSafe)On the host, after restart:
ping—ok,packs≥ 12,api_key_setboolean. Never inventrun_pack/run_questionsanswers if the key is missing.list_packs— pick anid.If a pack fits:
describe_packthenrun_pack. If none fits:run_questions(closed state + typed Choice / Noul / Score).
CLI: mcp_jev doctor · mcp_jev smoke · mcp_jev scan <path> · mcp_jev hosts print · mcp_jev hosts write all · mcp_jev config set-key · mcp_jev config status.
Verify
npm test # unit tests; mocked TypeSafe; no live key
./scripts/verify-mcp.sh # stdio JSON-RPC: initialize, tools/list, ping, list_packs
npm run smoke:packs # ping → list_packs → describe_pack + run_pack(example_state) for every pack
npm run smoke:packs -- --live # real TypeSafe from TYPESAFE_API_KEY or ~/.mcp_jev/.envDefault smoke:packs injects the same mocked systemOne pattern as npm test (no network). It prints a table (pack, ok, ms, error) and exits non-zero if any pack fails. --live is skipped in CI unless TYPESAFE_API_KEY is set and SMOKE_LIVE=1.
Recipes
run_questions (first-class; no exact pack)
Packs are shortcuts. Same systemOne path as run_pack. Not “write me a review”. After a pattern repeats 2–3 times, upstream a named pack.
Blind dogfood: invent typed questions before opening the pack list; use a pack only if it matches exactly — docs/DOGFOOD.md. Model-lane cascades with custom option ids → model route via run_questions (do not stretch model_router).
Example (public-API / changelog break — no pack): state { path, change_summary, symbols:[{id,kind,note}] } + Noul is_breaking_for_callers + Score doc_debt + Choice hottest_symbol over symbol ids plus none. Full recipe: docs/CUSTOM_JUDGMENTS.md.
i18n via run_questions (equal to run_pack i18n_copy)
Closed candidates[], same Login / Submit / Error loading demo as the pack. Extra Noul needs_locale_split means i18n_copy is not an exact match — stay on run_questions. Runnable: npm run smoke:blind-i18n (mocked) or --live.
{
"state": {
"path": "src/components/LoginForm.tsx",
"language": "tsx",
"framework_i18n": "next-intl",
"uses_i18n_api": false,
"locale_files_present": true,
"candidates": [
{ "id": "login_heading", "text": "Login", "kind": "jsx_text", "line": 12 },
{ "id": "submit_btn", "text": "Submit", "kind": "jsx_attr", "line": 40 },
{ "id": "load_error", "text": "Error loading", "kind": "toast", "line": 55 }
]
},
"questions": [
{
"id": "has_user_facing_hardcoded_copy",
"type": "noul",
"instructions": "Given `path`, `candidates`, and `uses_i18n_api`, does this file contain user-facing hardcoded copy that is not already going through an i18n API?",
"criteria": {
"true": "At least one candidate is user-visible copy that would ship in one language.",
"false": "Candidates are identifiers, logs, tests, or already passed through t() / useTranslations."
}
},
{
"id": "should_migrate_to_i18n",
"type": "noul",
"instructions": "Should the caller extract the user-facing strings in `candidates` into the project's i18n layer before a multi-locale ship?",
"criteria": {
"true": "Hardcoded user-facing copy should move to locale files / t() before shipping more locales.",
"false": "No migration needed: already i18n, copy is dev-only, or a multi-locale ship is not indicated."
}
},
{
"id": "i18n_debt",
"type": "score",
"instructions": "How much i18n debt does this file add to a multi-locale ship, given `candidates` and `uses_i18n_api`?",
"criteria": [
"Clean: no user-facing hardcoded copy.",
"Local leftover: a few strings, easy extract.",
"Cross-cutting: many strings or mixed buckets; needs a focused pass.",
"Blocking for a multi-locale ship: user-facing copy would ship untranslated."
]
},
{
"id": "hottest_candidate",
"type": "choice",
"instructions": "Which `candidates[].id` is the hottest string to extract first? Options are only those ids plus `none`.",
"criteria": {
"login_heading": "kind=jsx_text; text=Login; line=12",
"submit_btn": "kind=jsx_attr; text=Submit; line=40",
"load_error": "kind=toast; text=Error loading; line=55",
"none": "No single candidate stands out to extract first."
}
},
{
"id": "needs_locale_split",
"type": "noul",
"instructions": "Should labels and toasts in `candidates` land in different locale namespaces (UI strings vs errors) rather than one dump?",
"criteria": {
"true": "UI labels and error/toast copy should split across locale files or namespaces.",
"false": "One locale namespace is enough, or there is no user-facing copy."
}
}
]
}Blind-test protocol
Invent typed Choice / Noul / Score questions before opening
list_packs.Use a pack only if it matches exactly.
Otherwise
run_questions. Full protocol: docs/DOGFOOD.md.
computer_use_step (harness)
Code owns OCR / accessibility / DOM, clicks, and the writer LLM for free text. Jev only picks the next operation and a target from your closed catalogs.
Observe in the harness. Build
items[](and optionaloffscreen_items[]) with stable ids. Cap the catalog before 255 (Choice cap includesnone). Prefersource: "dom"when ids are DOM-closed;ax/ocrwhen that is what you observed. Shortobservation_summary. No screenshots, pixels, or image blobs in state (rejected asinvalid_state).run_packcomputer_use_stepwithgoal,app_or_url, that observation, recenthistory, andflags.One
systemOnecall fans outoperationplus a separate target Choice per op (click_target,type_target,offscreen_target) plusgoal_achieved,observation_stale,step_confidence. Each target question assumes its operation.Prefer additive
guidance:target_for,ignore_targets,effective_targets,writer_owns_typed_string,harness_hints. Rawanswersstay intact. Act only onguidance.effective_targets/guidance.target_for[operation].For
type_text/type_email, a writer LLM (or stored value) supplies the string.max_steps/max_candidatesstay in the harness.Example thresholds (tune on your traces): stop if
goal_achieved.noul ≥ 0.8oroperationisdone; re-observe ifobservation_stale.noul ≥ 0.65orstep_confidence.score < 1.5.
Example state:
{
"goal": "Sign in with the saved work account",
"app_or_url": "https://app.example.com/login",
"observation_summary": "Login form: email focused and empty, password empty, Sign in button, Forgot password link.",
"focused_field": "email",
"items": [
{ "id": "email", "role": "textfield", "label": "Work email", "region": "form", "source": "ax" },
{ "id": "password", "role": "textfield", "label": "Password", "region": "form", "source": "ax" },
{ "id": "sign_in", "role": "button", "label": "Sign in", "region": "form", "source": "ax" }
],
"history": [{ "action": "wait", "result": "form_visible" }],
"flags": { "loading": false, "login_required": true }
}model_router (per-turn lane)
Call at turn start, before tools. Map route.choice in code (unit-test the mapper; no TypeSafe key). Do not invent a sixth lane.
Closed lanes: fast_local | strong_reasoner | tools_heavy | ask_user | skip.
Lane | Meaning |
| Cheap/local or no model: lookup, format, one obvious tool |
| Ambiguous design, hard failure, plan not yet mechanical |
| Long tool / browser / shell loop |
| Missing preference, secret, or confirmation |
| Already done, blocked, or out of scope |
Example thresholds (caller-owned): route.confidence < 0.45 → ask_user; unsafe_or_irreversible.noul ≥ 0.70 → refuse or confirm; simple_lookup.noul ≥ 0.75 and difficulty.score < 1.5 → force fast_local.
Recipes table
Need | Pack |
Typed Choice / Noul / Score with no exact pack (incl. i18n + extra heads) |
|
Next GUI step from a closed element catalog |
|
Model cascade / per-turn compute lane |
|
Skill select from a closed list |
|
Command risk signals |
|
Generic diff review |
|
Repo tree / architecture / "try Jev on these files" |
|
Domain example: money / labor-hours / migration PR-shaped merge risk |
|
Item / SKU locale from a caller-supplied closed country list |
|
Claimed behavior vs named tests / CI |
|
One module’s imports/exports vs layer |
|
Hardcoded UI copy vs i18n ( |
|
Code-owned policy: keep thresholds in your functions (see src/policy-examples.ts; unit-test them without a TypeSafe key). Jev returns signals; your gate decides. Allowlist/sandbox still required for shell.
verify_gap: one claim vs named evidence → verifyGapCodeGate (ship | add_proof | block). boundary_check: one module’s imports/exports → fix (keep | extract | move_layer | unclear).
review_diff (staged review)
Nouls correctness / security / reliability / compat / test_gap → Choice hotspot_file from the closed files[] catalog → Score severity. Orchestration (comment, block, open a file) stays in the caller.
{
"intent": "Fail closed on reserved catalog ids",
"diff_summary": "Adds reserved-id checks and a unit test. No auth change.",
"files": ["src/packs/catalog-choice.ts", "test/computer-use.test.ts"]
}Example thresholds: request review if any Noul ≥ 0.65; block if security.noul ≥ 0.75 or severity.score ≥ 2.5.
pr_audit is a domain example pack (money / labor-hours / migration merge risk, common in ops/fintech) — not the universal PR pack. Keep the id. PR-shaped state only (title / body / files / diff_summary). General users should start with review_diff (diff) or code_audit (tree). Do not use pr_audit for a repo-tree scan. Never put experiment narrative in title/body. Large path-only batches (~40 files) inflate needs_review/block; path tokens (budget, migration, finance) move Nouls without reading bodies.
code_audit (full-repo / per-file scan)
Millisecond-tier structured engineering audit (layering / blast-radius / verification style checks). Expect ~network RTT per file; parallelize N workers. This is not a multi-second LLM review. Jev must not receive the monorepo as prose.
First-class harness: mcp_jev scan <path> (or node dist/cli.js scan). Do not dump a tree into pr_audit.
mcp_jev scan . --dry-run # files + signals; no TypeSafe
mcp_jev scan . # Pass 1, concurrency 8
mcp_jev scan . --concurrency 16 --pass2 5Walks the tree (respects .gitignore; skips binaries, images, lockfiles, node_modules, .git, generated dirs), builds compact signals, and calls code_audit through the same run_pack / systemOne path. JSONL to stdout (or --jsonl PATH); summary on stderr (top-K severity, primary_concern histogram, hottest paths, path-token-only flag count). Progress on stderr: files done/total, rate files/min, ETA. Missing API key → clear error (except --dry-run).
Pass 1 (default, all files): harness lists files → filter screenshots/binaries/generated vendor dirs → compact signals only → parallel run_pack code_audit → aggregate top problem_severity / most frequent Nouls.
Pass 2 (top-N only): resend the hottest files with a short excerpt (hard max 1200 chars; oversized → invalid_state) for confirmation. --pass2 N on the CLI.
6000 files / ~2 min class: keep Pass 1 signals-only. Concurrency default 8; 16–32 is typical for multi-k repos (MCP_JEV_SCAN_CONCURRENCY or --concurrency). --max-files N samples. --resume continues from .mcp_jev-scan-checkpoint.json (written every 50 files). Recipe: parallel Pass 1 → read top severity + path-token FP note → Pass 2 excerpts on top-K only.
mcp_jev scan . --concurrency 16 --summary-only --jsonl scan.jsonl
mcp_jev scan . --concurrency 16 --pass2 20 --summary-only
mcp_jev scan . --resume --summary-only --jsonl scan.jsonl # after interruptExample gate (src/policy-examples.ts gateCodeAudit): ok | glance | deep_review. Unit-test the gate without a TypeSafe key.
Pass 1 state (no body):
{
"path": "src/billing/invoice-total.ts",
"language": "ts",
"role_hint": "domain",
"signals": {
"loc": 12,
"import_count": 1,
"top_imports": ["money"],
"has_tests_nearby": false,
"touches_money": true,
"is_generated": false,
"complexity_heuristic": 2
},
"repo_context": "Billing module: invoice line totals."
}Optional Mode B: one call with files[] (paths only) + short batch_notes — Choice hotspot_file from that closed catalog, no bodies. If path is also set, single-file Mode A wins.
i18n_copy (hardcoded UI copy)
Shortcut pack when invented heads match exactly (the three Nouls + i18n_debt + hottest_candidate + primary_bucket). Extra head such as needs_locale_split → run_questions (recipe above, equal JSON). Per-file audit of hardcoded strings that should live in an i18n layer. The harness extracts a closed candidates[] catalog (max ~20). Jev does not rewrite JSX or locale JSON.
Nouls has_user_facing_hardcoded_copy / should_migrate_to_i18n / already_partially_internationalized → Score i18n_debt (0 clean → 3 blocking for a multi-locale ship) → Choice hottest_candidate from candidates[].id plus none → Choice primary_bucket (ui_copy | error_message | marketing | dev_only | mixed | none).
{
"path": "src/components/LoginForm.tsx",
"language": "tsx",
"framework_i18n": "next-intl",
"uses_i18n_api": false,
"locale_files_present": true,
"candidates": [
{ "id": "login_heading", "text": "Login", "kind": "jsx_text", "line": 12 },
{ "id": "submit_btn", "text": "Submit", "kind": "jsx_attr", "line": 40 },
{ "id": "load_error", "text": "Error loading", "kind": "toast", "line": 55 }
]
}Example gate (src/policy-examples.ts gateI18nCopy): ok | glance | block. Unit-test the gate without a TypeSafe key.
Update
Update from the GitHub checkout, not npm:
~/mcp_jev/scripts/update.sh # git pull + npm install + build; keeps ~/.mcp_jev/.env
# Windows: ~\mcp_jev\scripts\update.ps1Do not npm update -g mcp_jev or npx mcp_jev@latest. Public versions are GitHub Releases (v0.0.9 onward). Scheme: docs/RELEASES.md.
Restart the MCP host. update.sh refreshes the skill once to ~/.agents/skills/mcp_jev. Hosts that do not read that path: re-add once (do not also copy — nests mcp_jev/mcp_jev):
npx skills add pedroknigge/mcp_jev --skill mcp_jevSkill stays in sync
The agent skill lives in-repo at skills/mcp_jev/SKILL.md. Frontmatter description always starts with VERSION — (the package.json version + em dash). npx tsx scripts/sync-skill-catalog.ts / npm test fail if it drifts. This is the template for Pedro skills.
scripts/update.sh pulls the checkout and refreshes the skill once to ~/.agents/skills/mcp_jev (replaces that folder; never nests). Hosts that do not read that path: re-add once with npx skills add pedroknigge/mcp_jev --skill mcp_jev. Do not also copy.
Exact pack ids / question ids / state fields: skills/mcp_jev/references/pack-catalog.md (generated from src/packs/). npm test fails if a new pack or question id is missing from the skill or that catalog.
Say this to your agent
Install and configure mcp_jev from https://github.com/pedroknigge/mcp_jev using the install script and skill. Then run doctor, ping, and list_packs.
Or: run scripts/install.sh (refreshes the skill once to ~/.agents/skills/mcp_jev), paste the printed snippets, restart, doctor → ping → list_packs. Do not also npx skills add in the same pass.
Install for agents & IDEs
Easiest path: install script → one keyless command pointing at ~/.mcp_jev/bin/mcp_jev → mcp_jev doctor → restart → ping. Full stanzas in docs/INSTALL_AGENTS.md.
The server reads TYPESAFE_API_KEY from ~/.mcp_jev/.env (or $MCP_JEV_HOME/.env). Process env is a fallback only when the store is empty. Host configs must stay keyless.
Generic JSON (most hosts):
{
"mcpServers": {
"mcp_jev": {
"command": "/absolute/path/to/.mcp_jev/bin/mcp_jev"
}
}
}Windows wrapper: %USERPROFILE%\.mcp_jev\bin\mcp_jev.cmd.
Print or merge snippets: mcp_jev hosts print · mcp_jev hosts write all.
Cursor
Project: .cursor/mcp.json · User: ~/.cursor/mcp.json (project wins on name clash).
Skill: install.sh refreshes ~/.agents/skills/mcp_jev once. If you skipped the script, pick one: npx skills add pedroknigge/mcp_jev --skill mcp_jev or rm -rf ~/.agents/skills/mcp_jev && cp -R skills/mcp_jev ~/.agents/skills/mcp_jev. Never both.
Claude Desktop
Settings → Developer → Edit Config, then fully quit.
OS | File |
macOS |
|
Linux |
|
Windows |
|
Same keyless mcpServers JSON as Cursor.
Claude Code
claude mcp add --scope user --transport stdio mcp_jev -- /Users/YOU/.mcp_jev/bin/mcp_jevOr merge ~/.claude.json with the generic JSON. Skill: copy to .claude/skills/mcp_jev.
Codex
TOML, not JSON. ~/.codex/config.toml or .codex/config.toml:
[mcp_servers.mcp_jev]
command = "/Users/YOU/.mcp_jev/bin/mcp_jev"Or codex mcp add mcp_jev -- /Users/YOU/.mcp_jev/bin/mcp_jev.
Grok
~/.grok/config.toml / grok mcp add mcp_jev -- ~/.mcp_jev/bin/mcp_jev. Same TOML table [mcp_servers.mcp_jev].
Antigravity
~/.gemini/config/mcp_config.json or .agents/mcp_config.json — generic JSON, command = wrapper.
Other JSON / TOML hosts
Same wrapper command. Some editors use context_servers instead of mcpServers — see docs/INSTALL_AGENTS.md.
Agent instructions
You have mcp_jev (or you must install it from https://github.com/pedroknigge/mcp_jev). Jev is not chat. No
ask_jev.If the MCP tools are missing: tell the user to run
scripts/install.sh(orinstall.ps1) from that repo, paste the printed snippets, set the key once (config set-key/ install prompt), runmcp_jev doctor, restart the host.Always:
list_packs. Packs are shortcuts: if one fits,describe_pack→run_pack. If no pack fits, do not stop: build closed state + typed Choice / Noul / Score and callrun_questions. Side effects stay in your code. Never putTYPESAFE_API_KEYin chat. Ifping.api_key_setis false, runmcp_jev config set-key— do not embed the key in every host config.
Tools (closed catalog)
Tool | Args | What it does |
| none |
|
|
| JSON Schema, questions, |
|
| Validates state, calls TypeSafe |
|
| Fail-closed typed Choice / Noul / Score when no pack fits. Same |
| none | Versions, pack count, |
There is no free-form ask tool. list_packs / describe_pack / ping never call TypeSafe. Only run_pack and run_questions do. Teaching for the custom path: docs/CUSTOM_JUDGMENTS.md.
Packs
id | What Jev judges | What you still do |
| Domain example (ops/fintech): | Staged review: risk Nouls → file Choice over |
| Nouls correctness / security / reliability / compat / test_gap; Choice | Default generic PR/diff pack. Orchestration stays in the caller |
| Nouls | Pass 1: signals-only, ~RTT per file, N workers. Pass 2: short excerpt on top-N. Aggregate + |
| Noul | Load the skill in the host. Thresholds in your code |
| Nouls | Allowlist/sandbox still required. Signals only |
| Closed intent Choice, jailbreak + policy Nouls, urgency Score | Route / refuse / hand off in code |
| Catalogue item → one id from the caller’s closed | Pass your own country list. Write the country to your catalogue |
| Next GUI | Observe (OCR/AX/DOM), execute the op, writer LLM for typed text, stop rules |
|
| Map the lane in code. Thresholds stay in the caller |
| Nouls | Compute |
| Nouls | Extract / move / keep in caller code |
| Nouls | Truncate to ~20 candidates. |
Packs live in src/packs/ (in-repo). How to add one: CONTRIBUTING.md.
Breaking (locale_country 2.0.0): country Choice options are no longer a hardcoded country list. Callers must pass countries[] (closed catalog of their own ids, e.g. us, de, jp). unclear remains the pack-owned refuse option.
Architecture
flowchart LR
Agent[Agent] -->|stdio MCP| Server["mcp_jev"]
Server --> Packs[Pack registry]
Server -->|run_pack / run_questions| SDK["TypeSafeClient.systemOne"]
SDK --> API["POST /v1/systemone"]
API --> Jev["Jev"]
Jev -->|typed answers| SDK
SDK --> Server
Server --> Agent
Agent -->|gates and side effects| Code[Your code]Environment
Variable | Required | Default |
| Yes, for | From |
| No | SDK: |
| No |
|
| No | Used if |
| No |
|
| No | Alias for |
| No | Git checkout (default |
| No | Install-time host write ( |
| No | Dest for the one skill refresh (default |
| No | Default parallel workers for |
Repo .env is not auto-loaded. The user store ~/.mcp_jev/.env is. The store wins; process env is fallback only.
CLI: mcp_jev doctor · mcp_jev smoke · mcp_jev scan <path> · mcp_jev hosts print · mcp_jev config set-key · mcp_jev config status · mcp_jev config path.
Security
Key lives in
~/.mcp_jev/.env(0600). Never in git, chat, or host JSON. Process env is fallback only if the store is empty.ping/config status/doctornever print the key.scripts/update.shdoes not overwrite the key file.Run locally. Do not deploy this stdio binary as a public HTTP proxy.
Pack state can contain tickets and diffs — keep diffs summarized.
MIT licensed. Jev / TypeSafe are products of TypeSafe; this project is an independent open-source client.
Troubleshooting
Symptom | Fix |
| Non-interactive install without a key. Run |
| Same. Confirm |
| Same. |
| Key rejected (HTTP 401). Rotate at the TypeSafe dashboard, then |
| Re-read |
|
|
|
|
Wrong Node |
|
stdio pollution | Wrapper and server must not write to stdout. |
| Expected. mcp_jev is not on npm. Clone GitHub and run |
Scripts
./scripts/install.sh # happy path
./scripts/update.sh
./scripts/verify-mcp.sh # stdio smoke, no TypeSafe call
npm run smoke:packs # mocked run_pack for every pack
npm run smoke:blind-i18n # mocked run_questions-shaped i18n (closed candidates)
npm run build # tsc → dist/
npm start # node dist/index.js (MCP stdio)
npm test
npm run typecheck
mcp_jev doctor
mcp_jev smoke # same stdio check as verify-mcp.shLicense
Available Tools
5 toolsdescribe_packDescribe a Jev packA
Return a pack's JSON Schema state, Choice/Noul/Score questions, example state, and suggested agent workflow. Always describe before run_pack when the schema is unfamiliar.
| Name | Required | Description | Default |
|---|---|---|---|
| pack_id | Yes | Pack id from list_packs, e.g. pr_audit |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It states that the tool 'returns' information, implying a read-only operation, but does not explicitly say it has no side effects, require authentication, or describe any rate limits. The return content is listed, but deeper behavioral traits are left implied rather than stated.
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 description is two sentences with zero filler. The main purpose and return contents are front-loaded in the first sentence, and the crucial usage rule is placed second. Every word earns its place.
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?
For a simple one-parameter tool with no annotations and no output schema, the description does a solid job: it specifies what is returned, gives a usage trigger, and the parameter reference is well defined. It could be more explicit about the exact format or expected output structure, but given the low complexity, this is not a significant gap.
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?
Schema coverage is 100% – the single parameter pack_id is already clearly documented in the schema as 'Pack id from list_packs, e.g. pr_audit.' The tool description itself adds no additional meaning about the parameter, so the baseline of 3 applies without penalty or bonus.
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 uses a precise verb ('Return') and lists specific resources: JSON Schema state, Choice/Noul/Score questions, example state, and suggested workflow. This clearly distinguishes describe_pack from sibling tools like run_pack and list_packs, which execute and enumerate packs respectively.
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 second sentence gives an explicit directive: 'Always describe before run_pack when the schema is unfamiliar.' This directly tells the agent when to use this tool versus run_pack, which is the main alternative it would otherwise confuse with.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_packsList Jev packsA
List the closed catalog of TypeSafe Jev packs. Packs are shortcuts: if an id fits, describe_pack + run_pack. If no pack fits, do not stop — use run_questions with closed state + typed Choice/Noul/Score. There is no free-form ask tool.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses the catalog is 'closed' (static, read-only) and implies a safe listing operation. It does not describe the return format or any edge cases, but for a zero-parameter list operation this is a minor gap rather than a serious one.
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?
Two dense sentences front-load the purpose and then provide the complete routing logic. Every clause earns its place; there is no repetition of schema or annotation content.
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?
For a list tool with no parameters and no output schema, the description explains how it fits into the broader tool flow: how to proceed with a matching pack, how to fall back to run_questions, and that no free-form ask exists. An agent can invoke it correctly with full awareness of next steps.
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?
The tool takes zero parameters and the schema is empty, so the baseline is 4. The description adds no parameter details because none exist, and the routing guidance about 'id' refers to other tools, not this one.
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?
States a specific verb and resource: 'List the closed catalog of TypeSafe Jev packs.' It is clearly differentiated from siblings by framing packs as shortcuts and explicitly pairing them with describe_pack and run_pack, leaving no ambiguity that this tool only lists rather than executes.
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?
Provides an explicit decision rule: 'if an id fits, describe_pack + run_pack' and 'If no pack fits, do not stop — use run_questions.' It also warns against a nonexistent free-form tool. This is exemplary when-to-use guidance that leaves nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pingHealth checkA
Health: server version, TypeSafe JS SDK version, pack count, whether TYPESAFE_API_KEY is set. Never echoes the key.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses what the tool returns and explicitly states the key safety behavior: it never echoes the API key. It could additionally state that it makes no modifications, but a health check is reasonably understood as read-only.
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 description is a single compact sentence that lists the relevant details and a safety warning. Every word earns its place, and the most important facts are front-loaded.
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?
For a zero-parameter, read-only health tool with no output schema, this description is fully adequate. It tells the agent what information will be available and the key security constraint, leaving no critical gaps.
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?
There are zero parameters, so the description does not need to explain parameter meaning. The baseline of 4 applies since no parameter information is required.
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 states exactly what the tool reports: server version, SDK version, pack count, and API key presence. It clearly identifies this as a health check, which distinguishes it from the list/describe/run siblings.
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 usage is implied by the name and description: call it to check server health and configuration. However, it does not explicitly say when to use it versus the siblings, nor does it describe common scenarios like verifying connectivity or setup.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_packRun a Jev packA
Validate state and call TypeSafe System One (Jev) for that pack only. Returns typed answers (choice/noul/score), probabilities/confidence where the API provides them, and usage. Requires TYPESAFE_API_KEY. Does not run side effects.
| Name | Required | Description | Default |
|---|---|---|---|
| state | Yes | State object matching the pack's JSON Schema from describe_pack | |
| pack_id | Yes | Pack id from list_packs |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description takes on the full burden and does well: it discloses the API key requirement, states that no side effects are run, and describes the return content including typed answers, probabilities/confidence, and usage. This goes well beyond the schema fields and gives an agent a clear behavioral model.
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 description is compact and front-loaded: the main action appears first, followed by return details, authentication requirement, and side-effect note. Every sentence adds meaningful information with no filler.
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?
For a two-parameter tool with no output schema, the description covers inputs, return values, auth requirements, and side-effect profile, which is strong. It does not describe failure behavior when validation fails, but the essentials are sufficient for correct tool selection and invocation.
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?
The schema already provides 100% description coverage for both parameters, including pack_id sourced from list_packs and state matching describe_pack's schema. The description does not add additional parameter-level meaning, so the baseline of 3 applies.
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 clearly states a specific action ('Validate state and call TypeSafe System One (Jev) for that pack only') and identifies the resource (a pack). It distinguishes itself from the sibling tools by focusing on executing a single pack rather than listing or describing packs.
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 phrase 'for that pack only' implies usage on a single pack, but the description does not explicitly state when to prefer run_pack over list_packs or describe_pack, nor does it give any exclusions or prerequisites beyond the API key. Usage context is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_questionsRun typed custom questionsA
Typed custom path when no pack shortcut fits. Validate caller-built state plus typed Choice / Noul / Score and call the same TypeSafe System One path as run_pack. Not chat and not essay generation. Prefer run_pack when list_packs has an id (e.g. i18n_copy). Fail-closed schema: Choice is a closed option map (max 255; include a refuse key if needed), Noul is yes/no, Score is ≥2 ordered levels. Returns typed answers + usage. Requires TYPESAFE_API_KEY. No side effects.
| Name | Required | Description | Default |
|---|---|---|---|
| model | No | Optional TypeSafe model override (default JEV_MODEL / jev-latest). | |
| state | Yes | Caller-built JSON evidence. Closed and small — not a repo dump. | |
| questions | Yes | Typed questions: { id, type: choice|noul|score, instructions, criteria }. Not a free-form prompt. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden. It discloses key behaviors: 'No side effects', 'Requires TYPESAFE_API_KEY', 'Fail-closed schema', and 'Returns typed answers + usage'. It doesn't detail error handling or rate limits, but the provided information is strong for a read-like tool.
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 description is dense but well-structured: key purpose, usage guidance, schema fail-closed details, and constraints are front-loaded. Each clause adds value, though it could be slightly clearer for non-experts.
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?
Given the tool's complexity (typed questions, nested objects) and lack of output schema/annotations, the description is quite complete. It covers prerequisites (API key), side-effect profile, and schema constraints. Missing output details are noted but acceptable due to description's stated return of 'typed answers + usage'.
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?
Schema coverage is 100%, so baseline is 3. The description goes beyond the schema: it explains the purpose of 'state' (caller-built, closed, small), the structure of 'questions' (typed, closed option map, max 255, include refuse key), and the semantics of Noul and Score. This adds substantial meaning for correct parameter construction.
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 clearly states the tool's purpose: to run typed custom questions via a specific path ('TypeSafe System One') when no pack shortcut fits. It distinguishes it from siblings by explicitly mentioning 'run_pack' and noting it is 'Not chat and not essay generation.'
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 explicit guidance: 'Prefer run_pack when list_packs has an id' and states it is not for chat or essay generation. It also describes the fail-closed schema constraints, which are critical for correct usage.
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.0.9- Added
run_questions
4 tool updates
v0.1.0- First observed
describe_pack - First observed
list_packs - First observed
ping - First observed
run_pack
TDQS
Scored across 5 tools
Each tool has a distinct role: listing packs, describing a pack, running a pack, running custom questions, and health checking. The only potential confusion is between run_pack and run_questions since both invoke the same TypeSafe System One path, but their descriptions clearly separate pack-based from custom typed workflows.
Most tools follow a clear verb_noun pattern: list_packs, run_questions, describe_pack, run_pack. The one outlier is the one-word health tool 'ping', which breaks the pattern but is a common and recognizable convention.
Five tools is a well-scoped size for a focused server that handles pack listing, description, execution, custom question runs, and health checks. Each tool has a clear purpose and none feel redundant.
The server covers the full intended workflow: discover packs via list_packs, understand via describe_pack, execute via run_pack, handle non-pack cases via run_questions, and verify health via ping. Since the pack catalog is closed and free-form ask is intentionally excluded, there are no significant gaps.
Maintenance
Related MCP Connectors
A paid remote MCP for ZeroLang, built to return verdicts, receipts, usage logs, and audit-ready JSON
Deterministic contextual decision arbitration and action routing for autonomous software. Takes current state, context, or intent plus caller-supplied candidate actions, state transitions, routes, refusals, escalations, tools, or models and returns a deterministic ordered candidate field. Also provides persistent machine representations for memory, retrieval, indexing, and downstream coherence measurement.
A paid remote MCP for HyperFrames, built to return verdicts, receipts, usage logs, and audit-ready J
A paid remote MCP for ShipSwift, built to return verdicts, receipts, usage logs, and audit-ready JSO
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables MCP clients to call TypeSafe's JEV classifier and receive structured, typed judgments with probabilities for binary, choice, and scoring questions.MIT
- AlicenseAqualityBmaintenanceEnables frontier coding agents to delegate routine probabilistic judgments to TypeSafe Jev, providing calibrated triage signals for failures, attempts, completion, context ranking, findings, risk, and generic evidence-grounded questions.7MIT
- AlicenseCqualityBmaintenanceEnables browser agents to make typed, calibrated decisions via Jev's System One model within Aside workflows, supporting choice, score, and noul questions with safe action validation.64MIT
- AlicenseAqualityAmaintenanceEnables prototyping, running, and evaluating typed judgment questions against TypeSafe's Jev model, including accuracy, calibration, and threshold analysis.31MIT