jev-search
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., "@jev-searchsearch /home/me/notes/todo.txt for lines about feeling overwhelmed"
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.
jev-search-mcp
Find by meaning what keywords miss — as an MCP tool for your agents.
English · Русский
grep finds the words you typed. jev_search finds the lines that mean what you asked, even when they use different words.
This is a small stdio MCP server that gives any MCP-capable agent the jev-search CLI as one tool: jev_search.
What it is
Complementary semantic line search. Every nonblank line of a few small text files is judged against your intent by the TypeSafe Jev model. It adds to lexical search; it does not replace it.
Runs locally, next to your files. The server is a local process that your client starts over stdio. There is no port to open and nothing to host; only the model call itself is remote.
Works with every client that speaks MCP. Claude Code, Claude Desktop, OpenCode, or any other stdio MCP client.
Related MCP server: semantic-search-mcp
How it works
flowchart LR
subgraph local["Your machine"]
A["AI agent<br/>(MCP client)"] -->|stdio| B["jev-search-mcp"]
B -->|subprocess| C["jev-search CLI"]
end
C -->|HTTPS| D["OpenRouter"]
D --> E["TypeSafe Jev model"]The agent calls jev_search with a query and 1–8 absolute file paths. The server runs the pinned jev-search CLI, which reads the files, sends the nonblank lines and the query in one request, and returns a score for every line. The agent then merges these matches with its exact-search hits and reads the original context.
Why complement grep? In the upstream author's exploratory evaluation, across six simulated tasks, lexical search plus Jev recovered 29 of 34 labeled relevant passages, compared with 22 of 34 for lexical search alone. These were small, manually curated experiments, not a general accuracy claim.
Quick start
1. Install uv (skip this if uv --version already works), then open a new terminal.
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"# Linux / macOS
curl -LsSf https://astral.sh/uv/install.sh | sh2. Set your key. Create your own OpenRouter key with a spending limit at https://openrouter.ai/settings/keys and store it as JEV_SEARCH_API_KEY.
# Windows (PowerShell): paste the key when asked, then fully restart your terminal and MCP client
$s = Read-Host 'Paste your OpenRouter key' -AsSecureString
[Environment]::SetEnvironmentVariable('JEV_SEARCH_API_KEY', [System.Net.NetworkCredential]::new('', $s).Password, 'User')# Linux / VPS (bash): paste the key when asked; it is not shown and stays out of shell history
read -rsp 'Paste your OpenRouter key: ' K; echo
echo "export JEV_SEARCH_API_KEY='$K'" >> ~/.bashrc; unset K; chmod 600 ~/.bashrc; source ~/.bashrcUse ~/.bashrc, because ~/.profile alone misses non-login shells. This covers interactive shells only; for services or non-interactive launches, put the key in the client's env block. On macOS (zsh), run the same lines with read -rs 'K?Paste your OpenRouter key: ' and ~/.zshrc.
3. Install and connect (the example uses Claude Code; other clients are covered below).
uv tool install git+https://github.com/Vento741/jev-search-mcp@v0.1.1
jev-search-mcp --version # prints 0.1.1
claude mcp add --scope user jev-search -- jev-search-mcpUsing OpenCode instead? Run opencode mcp add --global jev-search -- jev-search-mcp and then opencode reload (see OpenCode).
To check the setup for free, ask your agent: "Run jev_search with dry_run on /home/me/notes/sample.txt for 'greeting'" (use the absolute path of one of your own files, e.g. C:\Users\you\notes\sample.txt on Windows).
If the shell reports thatjev-search-mcp is not found, run uv tool update-shell and open a new terminal.
# update to a newer release tag
uv tool install --force git+https://github.com/Vento741/jev-search-mcp@<new-tag>
# remove
uv tool uninstall jev-search-mcpOn Windows, close the MCP clients that run the server (Claude Desktop, OpenCode, Claude Code sessions) before updating: a running jev-search-mcp.exe locks its files, and the update fails with "Access is denied". If that happens, close the clients and run the same command again.
Connect your client
The server itself never takes a key as an argument; it reads JEV_SEARCH_API_KEY from the environment its client gives it. Clients differ in what environment they pass on, which determines where the key has to go.
Claude Code
claude mcp add --scope user jev-search -- jev-search-mcpClaude Code passes its whole environment to stdio servers, so the user variable from step 2 is enough. If you set the variable after starting Claude Code, fully restart it. With --scope user, the server is available in all your projects.
Claude Desktop
Claude Desktop passes only a small default set of variables (such as PATH and APPDATA) to servers, not your user variables. The key must therefore go into the config's env block, and command must be the full path to the executable.
Find the path:
where.exe jev-search-mcp(Windows) orwhich jev-search-mcp(macOS/Linux).Open the config file. You can use Settings → Developer → Edit Config, or open it directly at
%APPDATA%\Claude\claude_desktop_config.json(Windows).Add the server (merge it into
mcpServersif the file already has one), then fully quit and reopen Claude Desktop.
{
"mcpServers": {
"jev-search": {
"command": "C:\\Users\\you\\.local\\bin\\jev-search-mcp.exe",
"env": { "JEV_SEARCH_API_KEY": "<your-key>" }
}
}
}File: ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"jev-search": {
"command": "/Users/you/.local/bin/jev-search-mcp",
"env": { "JEV_SEARCH_API_KEY": "<your-key>" }
}
}
}CI covers only Windows and Linux; macOS is expected to work but is not tested.
In this file the key is stored asplain text. It lives in your user profile, so keep it private: never commit, sync, or share it.
OpenCode
opencode mcp add --global jev-search -- jev-search-mcp
opencode reload # the OpenCode app runs a background service that caches its config
opencode mcp list # expect: jev-search connectedOpenCode passes your environment to local servers, so the user variable from step 2 is enough (checked with OpenCode 2.0 on Windows). --global writes to ~/.config/opencode/opencode.jsonc and makes the server available in all projects; without it the server goes into the current project's opencode.json. If you set the key after OpenCode started, restart its background service with opencode service restart (or fully quit and reopen the app).
{
"mcp": {
"servers": {
"jev-search": {
"type": "local",
"command": ["jev-search-mcp"]
}
}
}
}If OpenCode is started by a service that does not have your variables, add "environment": { "JEV_SEARCH_API_KEY": "<your-key>" } to the server entry (plaintext, same warning as for Claude Desktop). Do not pass the key with opencode mcp add --env: it would end up in your shell history.
Any other MCP client
Use the generic stdio configuration. The same rule applies: unless your client is documented to pass on your full environment, put the key in env.
{
"mcpServers": {
"jev-search": {
"command": "jev-search-mcp",
"args": [],
"env": { "JEV_SEARCH_API_KEY": "<your-key>" }
}
}
}Zero-install alternative. To run without uv tool install, use uvx as the command. It starts more slowly and may contact GitHub each time it starts.
uvx --from git+https://github.com/Vento741/jev-search-mcp@v0.1.1 jev-search-mcpIn JSON this is "command": "uvx" with "args": ["--from", "git+https://github.com/Vento741/jev-search-mcp@v0.1.1", "jev-search-mcp"]. In Claude Code, use claude mcp add --scope user jev-search -- uvx --from git+https://github.com/Vento741/jev-search-mcp@v0.1.1 jev-search-mcp.
Variable | Values | Default |
|
|
|
| model identifier |
|
Calling TypeSafe directly (JEV_SEARCH_PROVIDER=typesafe) requires a key issued by TypeSafe. OpenRouter and TypeSafe keys are not interchangeable. Set these variables the same way as the key, either in your environment or in the client's env block.
Tool
The server is named jev-search and exposes one read-only tool.
jev_search(query, files, top_k=None, dry_run=False)
Parameter | Type | Rules |
| string | Required. The intent to find, in natural language. At most 512 bytes (UTF-8), one line, with nothing that looks like a secret. |
| list of strings | Required. 1–8 absolute paths to UTF-8 |
| integer or null | Optional, 1–64. Also returns |
| boolean | Default |
Example call
{ "query": "greeting", "files": ["/home/me/notes/sample.txt"], "dry_run": true }Dry-run output, for a two-line file:
{
"mode": "dry-run",
"requests": 1,
"payload_bytes": 984,
"rows": [
{ "file": "/home/me/notes/sample.txt", "line": 1, "original": "Hello, nice to meet you." },
{ "file": "/home/me/notes/sample.txt", "line": 2, "original": "The invoice is due Friday." }
],
"unjudged": { "reason": "dry-run", "candidates": ["l0", "l1"] },
"model": "typesafe/jev-1.13",
"provider": "openrouter"
}Real search (dry_run: false), measured 2026-09-30 through this MCP server; scores vary slightly between runs. Call:
{ "query": "greeting", "files": ["/home/me/notes/sample.txt"], "top_k": 3 }Output (file path synthetic, generation id truncated):
{
"mode": "sent",
"latency_seconds": 0.94,
"results": [
{ "file": "/home/me/notes/sample.txt", "line": 1, "original": "Hello, nice to meet you.", "probability": 0.8, "match": true },
{ "file": "/home/me/notes/sample.txt", "line": 2, "original": "The invoice is due Friday.", "probability": 0.04, "match": false }
],
"ranked_results": [
{ "file": "/home/me/notes/sample.txt", "line": 1, "original": "Hello, nice to meet you.", "probability": 0.8, "match": true }
],
"meta": {
"model": "typesafe/jev-1.13-20260917",
"generation_id": "gen-...",
"cost": 1.953e-05,
"input_tokens": 465,
"output_tokens": 38
}
}results contains every nonblank line with its file, 1-based line number and score, and match is probability >= 0.5. The scores are useful for ordering, but they are not calibrated probabilities, so cite files and lines rather than numbers. With top_k, an extra ranked_results list holds only the matches, best first.
Limits
These limits come from the upstream CLI, which deliberately works on small, reviewed context. It does not scan or truncate anything implicitly.
Limit | Value |
Files per call | 1–8, absolute paths, no directories or globs |
File types |
|
Combined size | ≤ 16 KB (16,384 bytes) and ≤ 64 lines across all files |
Line length | ≤ 2 KB (2,048 bytes) per line |
Query | ≤ 512 bytes |
Requests | exactly one per call, no retries |
Timeout | 330 s per call, set by this wrapper around the CLI subprocess (the CLI's own network timeout is 300 s) |
For a bigger file, search a reviewed excerpt of it instead. The CLI also rejects symlinks, paths where any component starts with . or contains secret, credential, password or id_rsa, and text that looks like a key or password.
Privacy & cost
Your lines leave your machine. Every selected nonblank line, plus the query, is sent to OpenRouter and on to TypeSafe. On the default route, the request pins TypeSafe as the only provider, with fallbacks disabled and data_collection: deny. Only send content you are allowed to share.
Real searches cost money. A two-line search cost about $0.00002 (measured 2026-09-30; prices vary). The cost grows with the number of lines.
Use your own key with a spending limit set in the provider's dashboard. Never share it.
A missing
costdoes not mean the search was free. A timeout or network failure may still have been charged. Nothing is ever retried automatically.dry_runis always free and never touches the network.
Documentation
For detailed scenarios (notes and docs, log triage on a VPS, CSV tickets, combining grep with semantic search, working within the limits), key management and troubleshooting, see the detailed guide (in Russian).
Credits & license
Built on larguesa/jev-search by Ricardo Pupo Larguesa (MIT), pinned to commit
8aa4035.Inspired by uehaj/jev-semgrep.
This wrapper: MIT © 2026 Vento741.
Not affiliated with TypeSafe or OpenRouter.
This server cannot be deployed
Maintenance
Related MCP Connectors
Code intelligence for coding agents: semantic, AST, graph, and full-text search. 279+ languages.
Ingest and search LogsLoom logs from coding agents.
Persistent memory for AI agents. Semantic recall by meaning, not just keywords. No signup needed.
Persistent memory for AI agents. Search, store, and recall across sessions.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides semantic code search capabilities that run 100% locally using EmbeddingGemma embeddings. Enables finding code by meaning across 15 file extensions and 9+ programming languages without API costs or sending code to the cloud.238-
- AlicenseAqualityDmaintenanceProvides semantic code search over codebases using local embeddings with natural language queries. Supports hybrid search, file watching, and respects .gitignore.1138 PyPI5MIT
- AlicenseNot gradedqualityDmaintenanceProvides local semantic search over files using embeddings, enabling directory indexing and natural language queries without external services.MIT
- AlicenseAqualityBmaintenanceEnables natural-language semantic search over your own local files through an MCP server, fully offline without API keys or a server daemon, with optional LLM-grounded answers and exact file:line sources.5MIT