envbert-mcp
MCP server for envbert environmental due diligence (EDD) text classification — supports both stdio (Claude Code, VS Code) and streamable HTTP (Claude.ai, any remote MCP client) transports.
Classifies EDD text — site assessment reports, groundwater monitoring logs,
geological surveys — into categories like Geology, Contaminants, and
Remediation Standards using a local DistilBERT model
(d4data/environmental-due-diligence-model).
No LLM fallback, sub-second inference, and your data never leaves your machine.
Features
- Two transports, one codebase — the same tool logic is exposed over stdio and streamable HTTP; the model loads once per process and is shared across all connections.
- Three MCP tools:
check_envbert_status— check whether the model is loaded and readyclassify_environmental_text— classify a single passageclassify_environmental_document— classify every paragraph of a document concurrently, with a category breakdown and low-confidence flags
- Fast — sub-second inference after warmup, no LLM round-trip
- Local-only — the model runs on your machine; HTTP mode only binds to
localhostby default
Installation
pip install envbert envbert-mcp
Verify:
python -c "from EnvBert.due_diligence import envbert_predict; print('OK')"
envbert-mcp --help
Note: the importable module is
EnvBert(capital E and B), notenvbert.
Usage
stdio (Claude Code / VS Code)
Default mode — no flags needed. Claude Code and the Claude Code VS Code extension spawn this as a subprocess automatically once configured (see below).
envbert-mcp
Streamable HTTP (Claude.ai / remote clients)
envbert-mcp --http
Runs on http://127.0.0.1:8000 by default. First call after startup takes
10–40 seconds while the model warms up; subsequent calls are sub-second.
# custom host/port
envbert-mcp --http --host 127.0.0.1 --port 8765
# check it's alive
curl http://127.0.0.1:8000/health
# {"status": "ready", "model_ready": true, "load_error": null}
Full setup walkthrough, including auto-start scripts and login-time
launchers for macOS/Windows, is in LOCAL_SETUP.md.
Connecting a client
Claude.ai (browser)
- Start the server:
envbert-mcp --http - In Claude.ai: Settings → Integrations (or Settings → MCP Servers)
- Add server URL:
http://127.0.0.1:8000/mcp - Name it
envbertand save
Claude.ai must be running on the same machine as the server — this is a localhost URL and isn't reachable from another computer.
Claude Code
~/.claude/mcp_config.json:
{
"mcpServers": {
"envbert": {
"url": "http://127.0.0.1:8000/mcp"
}
}
}
VS Code (Continue.dev)
.continue/config.json:
{
"mcpServers": [
{
"name": "envbert",
"transport": {
"type": "http",
"url": "http://127.0.0.1:8000/mcp"
}
}
]
}
GitHub Copilot (agent mode)
settings.json:
{
"github.copilot.chat.mcp.servers": {
"envbert": {
"url": "http://127.0.0.1:8000/mcp"
}
}
}
Auto-start
Scripts to start the server without remembering the command each time, and
optional login-time launchers, are in scripts/:
| File | Platform | Purpose |
|---|---|---|
start-unix.sh |
macOS / Linux | Start server in background, wait for health check |
start-windows.bat |
Windows | Start server minimized, wait for health check |
com.envbert.mcp.plist |
macOS | launchd agent — auto-start at login |
envbert-mcp-task.xml |
Windows | Task Scheduler task — auto-start at login |
See LOCAL_SETUP.md for install/uninstall steps for each.
Architecture
Claude Code / VS Code Claude.ai / remote clients
│ stdio │ HTTP POST /mcp
▼ ▼
envbert_mcp/server.py ←── FastMCP (single instance, both transports)
│
│ asyncio.to_thread() (keeps event loop free during ~1s inference)
▼
EnvBert.due_diligence.envbert_predict()
│
▼
DistilBERT (d4data/environmental-due-diligence-model)
Tools reference
check_envbert_status
No arguments. Returns:
{
"envbert_installed": true,
"model_ready": true,
"loading": false,
"load_error": null,
"load_time_s": 12.3,
"last_inference_ms": 850.0
}
classify_environmental_text
| Arg | Type | Description |
|---|---|---|
text |
str |
A sentence or paragraph of EDD text |
Returns label, confidence (0–1), and inference time. Confidence is the raw model estimate — below ~0.6, treat it as a best guess.
classify_environmental_document
| Arg | Type | Description |
|---|---|---|
paragraphs |
list[str] |
Paragraphs/sections, in document order |
low_confidence_threshold |
float |
Default 0.6 — paragraphs below this are flagged |
Returns per-paragraph results, a category distribution summary, and a list of low-confidence items worth a closer look.
Note on
confidence: this is a cosine similarity between the input text and a reference embedding for the predicted category — not a calibrated probability. It's a useful relative signal (higher = closer match) but shouldn't be read as "X% likely correct." Scores at or below 0.3 are already relabeledNot Relevantinternally before they reach you. Every response also includes ascore_basisfield as a reminder.
Why low-confidence flagging matters here
Without an LLM fallback, a low envbert confidence score (e.g. 0.42) is the
final answer — there's no second opinion baked in. classify_environmental_document
surfaces a low_confidence_items list explicitly so Claude can apply its
own judgement to exactly those paragraphs, rather than treating every
result as equally reliable.
Troubleshooting
Claude.ai says it can't connect:
- Confirm the server is running:
curl http://127.0.0.1:8000/health - Confirm Claude.ai is running on the same machine (not a remote browser session)
- Check your firewall isn't blocking localhost connections
Server starts but tools don't appear:
- Wait for warmup to finish —
check_envbert_statusreturns"model_ready": falseuntil it completes - Try disconnecting and reconnecting the MCP server in Claude.ai settings
envbert-mcp: command not found:
- Activate your venv first, or use the full path to the executable
More detail in LOCAL_SETUP.md.
envbert-mcp vs envbert-agent which to use
| This package (raw envbert) | envbert-agent | |
|---|---|---|
| Used by | Claude / MCP clients | CLI, pipelines, non-LLM consumers |
| LLM fallback | None | Yes — Ollama (local) or Azure |
| Typical latency | <1s always | <1s confident, ~10s on fallback |
| External dependencies | None beyond envbert | Ollama or Azure OpenAI |
| Confidence on ambiguous text | Raw model score only | LLM-resolved final label |
| Why this shape | Claude can reason over raw scores itself — a second hidden LLM call is redundant | No reasoning layer downstream; the agent must resolve ambiguity itself |
Both are legitimate — they're solving for different consumers of the classification, not competing implementations of the same thing.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file envbert_mcp-4.1.0.tar.gz.
File metadata
- Download URL: envbert_mcp-4.1.0.tar.gz
- Upload date:
- Size: 12.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b2dbd233010d054ea57afb749820babfebdf99e0710c652ca75129e8d1c048f
|
|
| MD5 |
eaec9f215ea37c4e8b739194d63f9231
|
|
| BLAKE2b-256 |
d969f5f1c609d033fff8778f53fde16a34dfe2b4796167e10eaf52b87299a23b
|
File details
Details for the file envbert_mcp-4.1.0-py3-none-any.whl.
File metadata
- Download URL: envbert_mcp-4.1.0-py3-none-any.whl
- Upload date:
- Size: 9.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5a45ae279d4f49b2ae38fca1d33ba5928aa54f38de1a6927c767a77c2cf6dd2e
|
|
| MD5 |
9feeffc65e9ccbe6a76ae5ee4e202628
|
|
| BLAKE2b-256 |
cd6dab36d212c6760925f1c6dcd48b4005aace9408b0cde427b09435adc26dc7
|