Skip to main content
Glama

brackenedge

Edge inference for pharmaceutical supply disposition, delivered as an MCP server. Given the sensor and handling data for a shipment leg, it returns one of three dispositions -- release, review, or quarantine -- and records every decision in a tamper-evident audit trail.

Two design constraints shape everything here:

  • Graceful degradation. Decisions run against an edge model when it is reachable and confident. When the model is down, errors out, or answers with low confidence, the engine falls back to a documented rule set instead of failing the decision. The provenance of every decision (model vs heuristic) and the reason for any fallback are recorded.

  • A reviewable audit trail. Every decision writes exactly one record to a hash-chained log before the result is returned. Editing or removing any past record breaks the chain, so an auditor can prove the trail is complete and unaltered. See brackenedge/audit.py.

The problem

A pharmaceutical distributor receiving shipments at warehouse docks needs a disposition (release, hold for review, or quarantine) for each arriving leg, computed at the dock rather than in a cloud round trip. Two things make this harder than a model call. The edge box's model may be down, slow, or uninstalled, and a stalled dock is a business problem — so the decision must still be made. And because these are release decisions for regulated product, every one has to be defensible to an auditor months later: what was decided, why, and whether a human or a model made the call.

Related MCP server: cronozen-proof

Architecture

The decision path is deliberately layered so the two constraints are structural, not bolted on:

  features ──> InferenceEngine.decide ──> Decision
                     │
                     ├─ Provider.available()?  no ─┐
                     ├─ Provider.infer()  error  ──┤
                     ├─ confidence < threshold  ───┤
                     │                             ▼
                     │                      heuristic.evaluate  (Provenance.HEURISTIC)
                     │  otherwise                  │
                     └─ model disposition ─────────┤  (Provenance.MODEL)
                                                   ▼
                                    AuditLog.append  (hash-chained, one per decision)
  • The engine talks only to the Provider interface. The model backend (providers/real.py, HTTP) and the deterministic test stub (providers/stub.py) are interchangeable, which is what lets the whole suite run offline and makes degradation a property of the interface rather than a special case.

  • The engine, not the provider, owns the degradation policy and the audit write. There is no path to a Decision that skips the audit record — that is enforced in one place, InferenceEngine.decide.

  • The audit log is a SHA-256 hash chain: each record hashes its own contents plus the previous record's hash, so a removed or edited record is detectable.

The contested design calls (why a hash chain, why degrade instead of fail closed, why a provider interface, where the confidence policy lives) are recorded in docs/adr/.

Layout

brackenedge/
  domain.py            # ShipmentFeatures, Decision, enums (validated, inert)
  heuristic.py         # rule-based fallback with documented thresholds
  engine.py            # InferenceEngine: the degradation algorithm + audit write
  audit.py             # hash-chained, tamper-evident AuditLog
  config.py            # env-driven EngineConfig + engine factory (validated)
  logging_setup.py     # structured JSON logging
  cli.py               # batch-scoring / audit-review command line
  server.py            # MCP server exposing the engine as tools
  providers/
    base.py            # Provider interface + output/error types
    stub.py            # deterministic, offline provider used by tests
    real.py            # HTTP provider for a real edge endpoint (stdlib only)
tests/

Install and test

make venv
make install
make test

make venv needs the python3.12-venv package present. If you cannot create a venv, the core and its tests depend only on the standard library plus pytest, so this also works:

python3.12 -m pip install pytest
python3.12 -m pytest

The test suite runs offline with no API key: it uses StubProvider, and tests/test_offline.py asserts that a decision opens no socket. Override the interpreter with make test PY=/path/to/python if you are not using .venv.

Running the server

make serve

serve runs python -m brackenedge.server. With no configuration it uses the deterministic stub provider so the server starts and degrades sensibly even with no model deployed. Configuration is via environment variables:

Variable

Effect

BRACKENEDGE_MODEL_ENDPOINT

Base URL of an HTTP edge model. When set, the real provider is used; otherwise the stub.

BRACKENEDGE_MODEL_NAME

Name recorded in the audit trail for the model.

BRACKENEDGE_AUDIT_PATH

File to append audit records to as JSONL. Reloaded and re-verified on startup.

Two more variables tune behaviour: BRACKENEDGE_CONFIDENCE_THRESHOLD (default 0.5), BRACKENEDGE_MODEL_TIMEOUT_S (default 2.0), BRACKENEDGE_MAX_BATCH (default 1000), and BRACKENEDGE_LOG_LEVEL (default INFO). Invalid values fail at startup with a clear message.

The server exposes three MCP tools: decide_shipment, verify_audit, and audit_tail.

Command line

The same engine is available as a CLI for batch scoring and audit review:

# score one shipment from stdin
echo '{"shipment_id":"S1","product_class":"cold_chain","max_temp_excursion_c":1.0,"excursion_minutes":60}' \
  | python -m brackenedge.cli decide

# score a batch from a file
python -m brackenedge.cli decide --input shipments.json

# review the audit trail (requires BRACKENEDGE_AUDIT_PATH)
python -m brackenedge.cli verify
python -m brackenedge.cli tail --limit 20

Input is a JSON object or an array of objects using ShipmentFeatures keys. Exit codes: 0 success, 2 configuration error, 3 input error (bad file, bad JSON, invalid features, batch over BRACKENEDGE_MAX_BATCH), 4 audit verification failed. Decisions and errors are logged as structured JSON to stderr, including measured per-decision latency.

Expected model endpoint contract

When BRACKENEDGE_MODEL_ENDPOINT is set, the real provider expects:

  • GET {endpoint}/health -> 2xx when the model is ready.

  • POST {endpoint}/infer with {"features": {...}} -> JSON {"disposition": "...", "risk_score": 0..1, "confidence": 0..1, "rationale": "..."}.

Anything else (connection refused, timeout, non-2xx, unparseable body) causes a graceful fallback to the heuristic, recorded with its reason.

The heuristic

The fallback is intentionally conservative -- in a pharma release decision, when in doubt you hold product for a human rather than release it. Rule precedence (first match decides; every triggered concern is still recorded):

  1. Broken seal -> quarantine

  2. Sustained cold-chain temperature excursion -> quarantine

  3. Large ambient excursion -> review

  4. Excessive transit delay -> review

  5. Otherwise -> release

Known limitations

  • The heuristic thresholds (brackenedge/heuristic.py) are defensible defaults, not validated SOP values. Wiring in a real, versioned SOP table is deferred; the constants are grouped at the top of the module for that reason.

  • The confidence threshold (default 0.5) is a starting policy value, not tuned against labelled outcomes.

  • real.py targets a simple HTTP endpoint; batching and streaming are out of scope for this milestone.


Glasshouse Data is an illustrative client; this repository is a self-directed reference implementation built to work end to end.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityInactive
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/J-X0/glasshouse-data-edge-inference-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server