JevLens
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., "@JevLensUse jev_ask to classify this support ticket: I was charged twice, please fix it."
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.
JevLens
See what Jev decided at every step of your agent run.
JevLens is a local MCP server plus a web panel for TypeSafe Jev decisions. It does not make decisions, does not route tools, and does not touch your agent's context. It wraps each systemOne call, records the full state, questions, answers, probability distribution, confidence and latency to an append-only JSONL file, and shows you a timeline so you can tell whether a weird agent behaviour came from Jev's judgement or from the LLM's generation.
Built for one-person, side-project, no-ops-budget developers:
No external services. No database, no cloud, no Docker. A JSONL file per day, greppable with
grepandjq.No frontend build. The panel is one HTML file; the chart library comes from a CDN.
No auth. The panel binds to
127.0.0.1and rejects otherHostheaders. It is a developer tool, not a SaaS.No harness lock-in. Standard MCP over stdio, so Claude Code, Codex, Cursor, OpenCode and any other MCP client can use it.
No extra model spend. JevLens only forwards calls you already make. It never calls an LLM on its own.
Fail-open by design. If the Jev API is unreachable,
jev_askreturns anundecidedresult and your agent keeps running.
state + questions ──▶ [jev_ask] ──▶ TypeSafe Jev API ──▶ answers + probabilities + confidence
│
├──▶ .jevlens/trace-YYYY-MM-DD.jsonl (append-only)
│
[jevlens ui] ──▶ http://127.0.0.1:8787 (3s polling, same file)The MCP server and the panel are two independent processes that share nothing but the JSONL file. Run the server while the agent works; start the panel only when you debug.
Quickstart (about 5 minutes)
# 1. Register it with your coding agent (Claude Code shown; see "Wiring" below for others)
claude mcp add jevlens --env TYPESAFE_API_KEY=$TYPESAFE_API_KEY -- npx -y jevlens mcp
# 2. Ask your agent to call the tool, e.g.
# "Use the jevlens jev_ask tool to classify this support ticket: I was charged twice, fix it today."
# 3. Look at what Jev actually returned
npx -y jevlens ui # then open http://127.0.0.1:8787No API key yet? Everything still works end to end against a deterministic offline provider, so you can try the panel and the tool shapes first:
npx -y jevlens ui --mock --port 8787The panel then shows the mock provider badge (mock) on every record, so you never confuse demo data with real decisions.
# 1. 注册 MCP 服务器(以 Claude Code 为例)
claude mcp add jevlens --env TYPESAFE_API_KEY=$TYPESAFE_API_KEY -- npx -y jevlens mcp
# 2. 让 Agent 调用 jev_ask,例如:
# “用 jevlens 的 jev_ask 工具判断这条工单:我被重复扣款了,今天必须解决”
# 3. 打开本地面板看决策时间线
npx -y jevlens ui --port 8787没有 API Key 时加 --mock,会用离线确定性 Provider 走完整个流程。数据只落在项目目录下的 .jevlens/trace-YYYY-MM-DD.jsonl,grep、jq 直接可查;面板只绑定 127.0.0.1,不做认证、不上传任何东西。jev_ask 遵循 fail-open:Jev 不可用时返回 undecided 并记录错误,不会中断 Agent。
Related MCP server: jev-mcp
Wiring
JevLens is a plain stdio MCP server. The only secret, TYPESAFE_API_KEY, is read from the environment and is never written to config files, traces or exports.
claude mcp add jevlens --env TYPESAFE_API_KEY="$TYPESAFE_API_KEY" -- npx -y jevlens mcpor in .mcp.json at the project root:
{
"mcpServers": {
"jevlens": {
"command": "npx",
"args": ["-y", "jevlens", "mcp"],
"env": { "TYPESAFE_API_KEY": "${TYPESAFE_API_KEY}" }
}
}
}In ~/.codex/config.toml:
[mcp_servers.jevlens]
command = "npx"
args = ["-y", "jevlens", "mcp"]
env = { TYPESAFE_API_KEY = "tsk_live_..." }In .cursor/mcp.json:
{
"mcpServers": {
"jevlens": {
"command": "npx",
"args": ["-y", "jevlens", "mcp"],
"env": { "TYPESAFE_API_KEY": "tsk_live_..." }
}
}
}In opencode.json:
{
"mcp": {
"jevlens": {
"type": "local",
"command": ["npx", "-y", "jevlens", "mcp"],
"environment": { "TYPESAFE_API_KEY": "tsk_live_..." },
"enabled": true
}
}
}Command: npx -y jevlens mcp (or jevlens mcp if installed globally), transport: stdio, and TYPESAFE_API_KEY in the child environment.
Tools
jev_ask — ask Jev, record everything
{
"label": "support-triage",
"state": { "subject": "I was charged twice, please fix this today", "channel": "email" },
"questions": {
"category": {
"type": "choice",
"instructions": "What is this ticket about?",
"criteria": { "billing": "money charged wrongly", "technical": "a feature does not work", "other": null }
},
"urgency": {
"type": "score",
"instructions": "How urgent is it?",
"criteria": ["routine", "within a day", "right now"]
}
}
}Returns structured JSON only — no prose for the model to misread:
{
"id": "0f4d5c6e-…",
"label": "support-triage",
"status": "answered",
"provider": "live",
"model": "system-one-2025-09",
"latency_ms": 812,
"confidence": { "min": 0.78, "mean": 0.845, "perQuestion": { "category": 0.91, "urgency": 0.78 }, "belowThreshold": [] },
"answers": {
"category": { "type": "choice", "choice": "billing", "confidence": 0.91, "probabilities": { "billing": 0.91, "technical": 0.07, "other": 0.02 } },
"urgency": { "type": "score", "score": 2, "confidence": 0.78, "probabilities": { "0": 0.05, "1": 0.17, "2": 0.78 } }
},
"hints": [],
"error": null,
"trace": "trace-2026-09-21.jsonl"
}status is "answered" or "undecided". An undecided result still contains an answer for every question (uniform probabilities, confidence 0) plus the recorded error, so a Jev outage degrades judgement instead of breaking the run.
Optional fields: model (per-call model override) and threshold (per-call alert threshold).
jev_trace — read recent decisions back
{ "limit": 20, "label": "support-triage", "below_threshold": 0.7, "include_payload": false }
Newest first, straight from the JSONL file. Set include_payload: false to drop the state body and keep the agent's context small.
jev_export — write a report
{ "format": "markdown", "label": "support-triage", "path": "reports/triage.md" }
Writes Markdown or CSV into .jevlens/exports/ (or your path) and returns { format, path, records, bytes }. Markdown is a paste-ready bug report: state, question definitions, answer table, probability distribution, confidence flags, hints and errors. CSV is one row per question with the record metadata repeated, so a spreadsheet can pivot on it.
The panel
jevlens ui --port 8787Timeline of every decision, newest first, with label, model, latency and minimum confidence.
Probability bars per question; the returned answer is the highlighted bar.
Confidence alerts: anything below the threshold is outlined in red and counted in the summary cards. The threshold is editable in the header and is persisted to
.jevlens/config.json.Auto-refresh every 3 seconds (polling, no WebSocket), pausable, and idle while the tab is hidden.
Expand a row for the raw
state, question definitions, hints, error text and the full record.Label filter, "flagged only" toggle, limit selector and a text filter over the whole record.
Confidence chart per decision (Chart.js from a pinned, SRI-hashed CDN URL; a text fallback appears if the CDN is unreachable).
One-click
.md/.csvexport.Deep links for sharing a view:
/?label=support&threshold=0.8&flagged=1&expand=1&q=billing.
The panel reads the same file the server writes; nothing is uploaded, and no port other than the one you choose is opened.
Question quality hints
Before each call, JevLens runs cheap static checks on your questions and attaches the results as advisory hints (hints in the tool response, an amber chip in the panel). Hints never block a call.
Code | Meaning |
| Two options mean nearly the same thing, so the probability split between them is uninterpretable. Compares labels and label+description text with word overlap plus character-bigram Dice, which works for English and CJK wording. |
| Fewer than two options: nothing to discriminate. |
| So many options that probability mass gets noisy. |
| Fewer than three buckets: a range that short cannot express much beyond a boolean. |
| More than eight buckets: adjacent positions become indistinguishable. |
| The same text reused at different positions of the scale. |
| A question with no instruction text; Jev answers from the option wording alone. |
| More than twelve questions in one call. |
Tune the overlap sensitivity with overlapThreshold in .jevlens/config.json.
Storage
.jevlens/
├── config.json # optional: threshold, port, rotation, model
├── trace-2026-09-21.jsonl # one decision per line
├── trace-2026-09-21-2.jsonl # rotation part 2 once maxRecordsPerFile is hit
└── exports/ # jevlens-<timestamp>.md | .csvAppend-only, one JSON object per line, daily files plus a per-file record cap. Torn lines from a killed process are skipped on read rather than breaking the panel.
jq -r '[.ts, .label, .status, .confidence.min] | @tsv' .jevlens/trace-*.jsonl
grep -c '"status":"undecided"' .jevlens/trace-2026-09-21.jsonlCredential hygiene is enforced at write time, not by convention: values stored under keys such as api_key, token, secret, password or Authorization are replaced with [redacted], any string equal to an environment secret is masked, and credential-shaped strings (sk…, ghp…, Bearer …) are scrubbed. There is a test that puts a fake key into state and asserts it never reaches disk.
Configuration
Environment | Purpose | Default |
| Jev API key (environment only; never persisted) | — |
| Jev endpoint override | SDK default |
| model requested for every call | provider default |
| trace directory |
|
| panel bind |
|
| alert threshold |
|
| records per file before rotation |
|
| Jev request timeout |
|
| force the offline provider | off |
.jevlens/config.json holds the same knobs (confidenceThreshold, storageDir, host, port, maxRecordsPerFile, model, mock, overlapThreshold). Precedence: built-in defaults < config file < environment < CLI flags.
{ "confidenceThreshold": 0.8, "maxRecordsPerFile": 2000, "overlapThreshold": 0.55 }CLI
jevlens mcp start the MCP server on stdio (what your agent launches)
jevlens ui start the local decision timeline
jevlens inspector launch the official MCP Inspector against this server
jevlens help usage; -v / --version prints the versionjevlens inspector runs the official MCP Inspector against jevlens mcp via npx and prints the
http://127.0.0.1:6274/… URL (recent Inspector versions add an auth token to it). From there you can
call jev_ask by hand and watch the JSONL file grow.
Development
npm install
npm run typecheck # tsc -p tsconfig.dev.json (src + tests + examples)
npm run build # tsc → dist/
npm test # node --test on TypeScript sources, no build step needed
npm run check # all three
node examples/seed-trace.ts # write a few demo decisions with the offline providerTypeScript, Node 22+, ESM, and exactly three runtime dependencies: @modelcontextprotocol/sdk, @typesafe-ai/sdk and zod v4. Tests use the built-in Node runner and cover storage rotation and torn lines, config precedence, credential scrubbing, question-quality heuristics, fail-open paths (unreachable API, missing answers, unwritable storage), the mock provider's probability invariants, Markdown/CSV correctness, the HTTP API of the panel, and a real MCP client talking to the built server over stdio.
Publishing:
npm publish --access public # prepublishOnly runs a clean build plus the test suiteWhat JevLens deliberately does not do
Common Jev harness direction | JevLens |
Use Jev for tool selection or risk gating | Records and displays decisions; makes none |
Filter tool output or compress context | Never touches the agent's context |
Compare Jev against other models | Traces one agent run at a time |
Ship a preset question bank or linter | Shows what your questions actually returned |
Enterprise audit and compliance | Local files, no accounts, no quotas |
Also out of scope for v0.1: databases, indexes, query languages, auth, multi-tenancy, WebSocket push, automatic code changes, decision-chain orchestration.
Later directions that fit the same positioning: decision-chain visualisation (linking related calls into a tree), local PII masking before the write, read-only sharing of an exported run, and a tighter loop with a Jev question-quality linter.
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Local-first, governed memory and session continuity for AI coding agents. No cloud, no telemetry.
Project memory for coding agents: requirements, decisions, code graph and delivery telemetry.
Codebase graphs, caller impact analysis, and recorded project context for AI coding agents.
Cross-agent artifact workspace with provenance across Claude Code, Codex, Cursor, LangGraph.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables recording and analyzing AI agent execution traces, including event logging, metric computation, loop detection, and JSON export for debugging agent behavior.MIT
- AlicenseAqualityBmaintenanceProvides coding agents and CI with a typed decision layer that sends bounded state and questions to Jev, then returns deterministic actions for review, risk assessment, requirement checks, and verification.9MIT
- 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
- AlicenseNot gradedqualityBmaintenanceEnables coding agents to query a Jev model for next-tool recommendations, exposing tools to check status and request tool-choice predictions, while logging all decisions for review.MIT