handoffpack — MCP structured-card translator
Deterministic codec + guards + MCP server for HP1 structured handoff cards. Turns agent handoffs, session logs, and recurring-instruction files into compact structured cards. All deterministic work runs locally; the server never calls an LLM API and holds no API keys.
Install
Python 3.11+ required.
# From PyPI (once published):
pip install handoffpack
# Pre-publish / local: from the package directory
pip install .
# or editable, with test deps:
pip install -e .[dev]
Core codec/guards tests run with stdlib + pytest only; the mcp package
is needed only to run server.py.
Register the MCP server (Claude Code)
python -m handoffpack.server # stdio transport, run directly
claude mcp add handoffpack -- python -m handoffpack.server
Other clients (Cursor, etc.): use the same command in their MCP server
registration UI. A handoffpack console script is also installed as an
alias for python -m handoffpack.server.
License key (paid add-ons only)
The 4 MCP tools (encode / decode / compact_to_l2l / verify) are
FREE and unlimited. Only paid add-ons (e.g. the full hp-instructions
conversion run) require a key. The verifier is fully offline (embedded
Ed25519 public key, no phone-home). Key discovery precedence:
export ANIMA_LICENSE=ANIMA1.xxxxx... # macOS/Linux (recommended shared bundle key)
set ANIMA_LICENSE=ANIMA1.xxxxx... # Windows cmd
$env:ANIMA_LICENSE="ANIMA1.xxxxx..." # Windows PowerShell
# HP_LICENSE remains supported as a handoffpack-specific override.
# or place the key on the first line of ~/.handoffpack/license
# or pass --license <KEY> to hp-instructions
hp-instructions --check (drift scan) is free; a full conversion run
requires a plus-tier (or higher) ANIMA1 key carrying the handoffpack
entitlement. Current early-access test keys expire on 2026-09-30 UTC; the
commercial policy can be changed at issuance without replacing the clients.
Layout
mcp-translator/
├── pyproject.toml
├── src/handoffpack/
│ ├── legend.json # public card schema (typed slots + kv pairs)
│ ├── codec.py # assemble/parse/validate + chars/4 token estimator
│ ├── guards.py # breakeven passthrough, BAN-field rule, nuance heuristic
│ ├── license.py # offline Ed25519 license verifier (paid add-ons)
│ ├── adapter_instructions.py # hp-instructions CLI (CLAUDE.md -> HP1 cards)
│ └── server.py # MCP server: encode / decode / compact_to_l2l / verify
└── tests/
Run tests
pytest # 114 tests
Build & publish (maintainer)
python -m build # produces dist/*.whl + dist/*.tar.gz
python -m twine upload dist/*
If build is unavailable offline, an equivalent wheel can be produced
with python -m pip wheel . -w dist --no-deps --no-build-isolation.
Architecture notes (caller-does-semantics)
- Deterministic work (card assembly, parsing, schema validation, guards, token estimation) is local and pure. The server never calls an LLM API and holds no API keys (zero-server-cost invariant).
- Semantic work (slot extraction, compaction keep/drop judgment) belongs
to the CALLING model:
encode(slots={...})— the caller extracts TASK/ROLE/IN/DO/OUT/LIM/BAN from its own context and passes them directly (mode: "slots",confidence: "caller"). Passtexttoo for token metrics.compact_to_l2l— two-call protocol. Call 1 (session_textonly) returns a per-segmentscaffold+fill_slots_and_recall+ a crude deterministic fallback. Call 2 addssegment_slots={"<seg>": {slots} | "TASK string"}.decode/verify— deterministic.
- Freeform
encode(text=...)without caller slots returns a deterministic skeleton card plusfill_slots_and_recallguidance for a second call. - MCP sampling (
session.create_message) survives only as an OPTIONAL, capability-detected upgrade path (deprecated upstream: MCP 2026-07-28 spec RC, SEP-2577; replaced by Multi Round-Trip Requests, SEP-2322; Claude Code never implemented it, anthropics/claude-code#1785). It is OFF unless the operator setsHP_ENABLE_SAMPLING=1AND the client advertises the capability; results are always deterministically re-validated. Nothing depends on sampling. - Token estimates use ceil(chars/4). Crude by design; never used for claims or billing.
Guard behavior
- Inputs under ~70 estimated tokens are returned unchanged with a reason (encoding overhead exceeds savings below breakeven).
- BAN slots accept plain forbidden actions only. Conditional negation ("X unless Y", "only outside Z") is rejected; express the condition as a positive LIM constraint instead.
- Prose with high conditional-clause density gets an advise-skip verdict instead of a lossy card.
Metadata
Release files for handoffpack 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| handoffpack-0.3.2.tar.gz | 43.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| handoffpack-0.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 77.0 kB
Release files / handoffpack-0.3.2.tar.gz
| Download URL | handoffpack-0.3.2.tar.gz |
|---|---|
| Size | 43.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7f399261cc296ee91a5156691efd8b994235be6c386b155d0c9a2dfd6f3f6e2c
|
|
BLAKE2b-256 checksum How to use checksums |
91697459d20f3ebb9b1e0135946b4fd9df4c0fa06aa0347a5a66e291aca155a6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|
Release files / handoffpack-0.3.2-py3-none-any.whl
| Download URL | handoffpack-0.3.2-py3-none-any.whl |
|---|---|
| Size | 33.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
551330cb5457c24a527a68d841d12fc65a84b5a22ae1179827d82b20f1c4a0aa
|
|
BLAKE2b-256 checksum How to use checksums |
773d9aa47b606993a5fe18637935e6a568f46826cc9a624291199ab4db8c215c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|