SafetyPack MCP
by monoqlo78
README.md
# SafetyPack MCP
An **opt-in, local, encrypted project-memory MCP** for GitHub Copilot, Claude Code,
Codex and other local stdio MCP clients. Save decisions, changes and checkpoints
so another session or client can resume from explicit evidence rather than guesses.
**This repository contains only the local MCP.** No Alibaba Cloud account, Qwen
API key, Docker, web frontend, cloud backend or separate running service is needed.
It does not call a cloud LLM or expose an HTTP port. Optional neural search uses
fixed local embedding and reranking models, independently of the host's GPT,
Claude or other conversational model.
The older Alibaba/Qwen web application is a separate project:
[safe-memory-platform](https://github.com/monoqlo78/safe-memory-platform).
Its deployment history and cloud-usage claims do not describe this MCP.
The original MCP-only Git history has been extracted into this repository.
Use `/safetypack` where the client supports the supplied skill, or explicitly ask
the agent to "use SafetyPack to save/resume/search this project." Registering the
server is not permission to collect every conversation or tool call.
**License:** [MIT](LICENSE), including commercial use.
See [commercial-use consultation and sponsorship](#license-and-sponsorship)
for voluntary ways to support development.
## Download
- [Download the standalone source ZIP](https://github.com/monoqlo78/safetypack-mcp/archive/refs/heads/main.zip), or clone this repository as below.
- [Releases and wheel downloads](https://github.com/monoqlo78/safetypack-mcp/releases) provide versioned packages. Model weights and private memories are never bundled.
Only this repository/package is needed. Do not clone the Alibaba application to
install this MCP. Windows is the supported default for user-bound DPAPI encryption;
Python 3.11+ is required. Prefer a local folder outside cloud-sync directories.
## Install on Windows
Clone, or extract the ZIP and open a terminal in its root:
```powershell
git clone https://github.com/monoqlo78/safetypack-mcp.git
Set-Location .\safetypack-mcp
python -m venv .venv-safetypack
.\.venv-safetypack\Scripts\python.exe -m pip install --only-binary=:all: "."
.\.venv-safetypack\Scripts\safetypack.exe status
.\.venv-safetypack\Scripts\safetypack.exe client-config
$safetypack = (Resolve-Path .\.venv-safetypack\Scripts\safetypack.exe).Path
```
For a downloaded wheel instead of source, create a virtual environment in a
permanent local folder, then install the wheel with
`python -m pip install --only-binary=:all: PATH_TO_DOWNLOADED_WHEEL.whl` using that
environment's interpreter. `safetypack client-config` supplies the same registration
instructions. Skills are optional; an explicit request to use the MCP also works.
Merge the printed `mcpServers.safetypack` entry into your client's MCP
configuration. It uses the absolute interpreter path, so no global PATH changes
are needed. Do not replace existing servers or copy existing API keys into this
repository. Client-specific examples are in [integrations](integrations/README.md).
The store defaults to `%LOCALAPPDATA%\SafetyPack`. Use `--root` **before** the
subcommand to override it. Keep the active store outside OneDrive, network shares,
and source control. Use the same store root from all clients of the same Windows
user. The client may start the stdio process eagerly, but it does not create a DB,
load a model, start a watcher, or write memory until an explicit tool operation.
Prebuilt dependencies avoid resource-intensive native builds, particularly on
Windows ARM64. If no compatible wheel is available, installation fails instead
of silently compiling a toolchain.
## Workflow
1. Explicitly request SafetyPack and choose save, resume, or search.
2. Call `safetypack_activate` with the current project folder and client label.
Default reads are PUBLIC-only. Enable `allow_internal` only after approving
disclosure of INTERNAL memory to this host and potentially its cloud model.
3. Save concise observations with `memory_append`, or state and next actions with
`checkpoint_save`. Preserve the checkpoint revision for subsequent updates.
4. From another client, activate the **same project folder** and call `handoff_get`.
Validate current files/commit state before acting on historical instructions.
5. Do nothing between explicit requests. No periodic saves, automatic filesystem
scanning, transcript harvesting, compaction loop, or overnight indexing.
Checkpoints are INTERNAL. A PUBLIC-only session will not receive them. Session
handles are project-scoped capabilities, not proof of a client vendor's identity.
Neither a host's client name nor a model-written `allow_internal` value substitutes
for the user's approval in the host UI.
Activation uses authenticated, stateless session handles, so opening a new reader
does not consume history quota. The sanitized client label and purpose are
returned to the caller, not stored automatically. Include useful provenance in
the explicitly saved note/checkpoint. Project deletion revokes its handles.
### MCP tools
| Tool | Purpose |
| --- | --- |
| `safetypack_activate` | Explicit project activation and disclosure scope |
| `memory_append` | Sanitized evidence, with proposal labels and explicit supersession |
| `checkpoint_save` | Revision-checked per-session state and next steps |
| `handoff_get` | Size-bounded cross-session handoff |
| `memory_search` | Evidence-gated lexical or local neural hybrid retrieval |
| `memory_reindex` | Explicit local neural passage indexing; no downloads |
| `memory_get` | Allowed record and provenance |
| `memory_status` | Storage/limit status without activation |
The `safetypack` MCP prompt supplies the same opt-in workflow. How a prompt or
skill maps to `/safetypack` is client-specific; it is not a universal MCP command.
## What is unified
Storage encryption, vector generation, retrieval and policy enforcement live in
this package, not in agent instructions. Changing the conversation model does
not change the store's vector space or key. GPT can compose the checkpoint in
the host just as another model can; no additional GPT subscription/API is needed.
Version 0.2 uses **exact word/Japanese character features with corpus weighting**
to decide whether lexical evidence exists. Hash collisions from the v0.1 vector
index can no longer admit unrelated results. Existing legacy vectors remain for
format compatibility but are not used as evidence in the new search.
Optional **local multilingual neural embeddings plus cross-encoder reranking**
retrieve paraphrases and cross-language evidence. Dense similarity only selects
up to 24 candidates: a separate model jointly reads the question and each passage
to assess relevance. A high embedding cosine alone cannot produce a confident
match. The service fixes both model revisions, artifact hashes,
pooling, prefixes, dimensions, chunking and vector encoding. Changing a host model
does not change these. Embeddings are not encryption or anonymization.
Version 0.2 reads existing v1 stores. New stores and explicit writes use store
format 2 so old v0.1 clients fail closed rather than ignore superseded/proposed
records. Back up before upgrading, then update/restart every connected MCP
client. Encryption keys and existing record IDs are preserved; no bulk plaintext
export or automatic neural reindex is required for migration.
Content, paths, vectors, checkpoint text and provenance are AES-256-GCM encrypted
before SQLite receives them. Records are compressed first when that reduces their
size. Windows CurrentUser DPAPI wraps the random data key.
Opaque record/project IDs, record kind/revision and storage sizes remain visible.
This is encrypted-record SQLite, **not full-file SQLCipher**. Retrieval decrypts
a bounded set of records in process memory; there is no plaintext disk vector
index or plaintext full-text index.
## Higher-precision retrieval and local neural setup
Install the optional inference dependencies and explicitly download the pinned
public models. Neither step sends project data to a model service:
```powershell
.\.venv-safetypack\Scripts\python.exe -m pip install --only-binary=:all: ".[neural]"
& $safetypack neural-setup --allow-download
& $safetypack neural-status
& $safetypack reindex --project "C:\Projects\Example"
```
For wheel-only installations, replace `".[neural]"` with the downloaded wheel
path plus extras, for example
`"C:\Downloads\safetypack_local-0.2.0-py3-none-any.whl[neural]"`.
The same explicit `neural-setup` and `reindex` commands then apply.
The model cache lives under `%LOCALAPPDATA%\SafetyPackModels`, separate from
encrypted memories. Model files are not included in memory backups or Git.
The two bundles occupy approximately **259 MiB total**, excluding Python
dependencies. Their revisions, sizes and SHA256 hashes are compiled into the
package and checked before inference:
| Stage | Pinned model | Revision | License |
| --- | --- | --- | --- |
| Candidate embeddings | `Xenova/multilingual-e5-small` | `761b726dd34fb83930e26aab4e9ac3899aa1fa78` | MIT |
| Cross-encoder reranking | `cross-encoder/mmarco-mMiniLMv2-L12-H384-v1` | `1427fd652930e4ba29e8149678df786c240d8825` | Apache-2.0 |
Missing/tampered assets fail closed; normal retrieval never downloads replacements.
After moving to another PC, set up the same pinned models and explicitly reindex
the relocated project to update its model path.
`--model-dir` and `--reranker-dir` select separate cache directories for setup,
status and CLI reindexing. These contain public weights only, never memories.
`memory_search` modes:
| Mode | Behavior |
| --- | --- |
| `auto` | Exact lexical retrieval until this project is explicitly indexed; hybrid afterward |
| `lexical` | Exact lexical evidence only; never starts a neural worker |
| `hybrid` | Requires a complete, current index and both pinned models; locally reranks dense candidates |
Saving a note/checkpoint does not automatically run a neural model. When relevant
indexed content changes, hybrid search reports an incomplete/stale index instead
of silently using old embeddings or downgrading to lexical retrieval. Explicitly
call `memory_reindex`, or deliberately request `mode="lexical"`.
Reindexing covers each record with overlapping 320-character passages at a
256-character stride, including the end of long documents. Whitespace-only
windows are omitted. It commits atomically
after inference, aborting if content changed meanwhile, and does not change the
content revisions used by checkpoint compare-and-swap. Model token-budget errors
fail the operation rather than silently truncating evidence. Index vectors are
normalized float16 values inside authenticated, compressed record payloads.
### Do not turn retrieval candidates into unverified facts
- `status="no_match"` means insufficient evidence: do not answer from the nearest
unrelated record. Exact code identifiers/numbers must match; neural similarity
cannot substitute `SP-404` for a request about `SP-999`.
- `status="ambiguous"` means competing evidence needs source inspection or user
clarification. It also covers a lexical match rejected by the reranker.
Similarity, coverage and reranker scores are **not probabilities of truth**.
- `status="matched"` means retrieval gates passed, not that a statement is true.
`verified_by_safetypack` is always false. Hybrid `score`/`rerank_score` are raw
relevance logits, not normalized confidence percentages. `match_basis`
distinguishes reranked evidence from lexical-only candidates needing review.
- `answer_support="not_assessed"` is explicit: this MCP retrieves records, not
answers. A record about the correct file/role may still omit the requested
approver, date, version or reason. Check every requested detail against the
cited text; report missing details as **not recorded**, never infer them.
- Results include record ID, source, timestamps, evidence label and excerpt
offsets. Use `memory_get` for full evidence and check current files before acting.
- Set `evidence_kind="proposed"` for plans, `"reported"` for reported information,
or `"observed"` for observations. These are caller labels, not attestations.
An observed entry requires a non-sensitive source reference.
Proposals are excluded from normal search unless explicitly requested.
- When a decision replaces another, pass the old record IDs in `supersedes`.
Old records remain accessible by ID but are excluded from normal search and
handoff. A proposal cannot retire an actual decision. Concurrent conflicting
supersessions fail rather than overwriting each other.
Multiple near-tied current decisions are flagged for review. This is not a
general contradiction detector: if older facts were never marked superseded,
the service cannot infer that every newer statement is correct.
### Resource limits
| Resource | Limit |
| --- | --- |
| Project catalog | 256 projects |
| Project records | 2,000 including project metadata; stateless handles consume none |
| Record text | 16,384 characters (checkpoint summary + next steps combined) |
| Active DB + WAL | 64 MiB; SQLite pages conservatively capped near 21 MiB to leave WAL headroom |
| Search response | Up to 20 previews, each about 1 KiB of JSON; explicit `memory_get` for full text |
| Handoff response | 1,000-24,000 JSON characters; default 12,000 |
| Concurrent writers | Serialized local file lock with a bounded 15-second wait |
| Neural reindex | At most 2,048 passages per project per explicit operation |
| Hybrid reranking | At most 24 candidate passages; near ties require review; weaker tails are omitted |
| Neural runtime | Short-lived local CPU workers, one inference thread each; 180-second timeout per worker call |
Quota errors do not silently delete history. Existing projects can still activate
new readers at the record quota. Export a backup before explicitly deleting an
old project's live records. An explicitly installed model consumes cache space;
inference temporarily consumes substantially more RAM/CPU than lexical search.
Workers exit after their bounded call. There is no periodic cleanup/indexing task.
On Windows a Job Object owns the actual interpreter and its descendants,
including venv redirector children, so a timeout or owner exit does not leave
that inference job running. Lexical search never launches either worker.
## Recovery
```powershell
& $safetypack backup "D:\Backups\project-memory.smpx"
& $safetypack --root "C:\Users\YOUR_USER\AppData\Local\SafetyPack-Restored" restore "D:\Backups\project-memory.smpx" --confirm-recovery
```
The CLI prompts privately for a recovery passphrase (at least 16 characters).
Do not put it in a command, skill, chat, environment file, or repository.
Archives are compressed then authenticated/encrypted using a password-derived
key. Keep a high-entropy recovery passphrase separately from the archive.
Recovery deliberately permits a new machine to rewrap the data key under the
destination Windows user. **Possession of the archive and passphrase authorizes
recovery; this does not cryptographically prove the same human or Microsoft
account.** DPAPI-only files are not promised to survive Windows migration tools.
A matching username is not sufficient. Recovery refuses an existing nonempty
store. Do not delete the original until the restored store is usable.
If the project folder moved, explicitly rebind its stable project ID:
```powershell
& $safetypack --root "C:\Users\YOUR_USER\AppData\Local\SafetyPack-Restored" relocate-project "C:\OldPC\Project" "D:\Projects\Project"
```
To free a project's quota, explicitly remove just its live records:
```powershell
& $safetypack delete-project "C:\Projects\Example" --confirm-delete
```
This is logical deletion, not assured physical erasure or backup revocation.
Neither administrative command is exposed as an agent-callable MCP tool.
## Legacy Safe Memory Packs
```powershell
& $safetypack import-pack "D:\Packs\example.smp.json" --project "C:\Projects\Example"
```
Explicit local imports are limited to 4 MiB / 500 entries. Imported text is
sanitized and revectorized locally, always as INTERNAL. CONFIDENTIAL, SECRET,
EPHEMERAL and entries with restrictive query/LLM flags are skipped. Old vectors,
policy permission grants and ledger authenticity are not trusted. Imports do not
upload anything. They save entries incrementally; a quota/storage failure reports
how many were saved, so do not blindly retry the whole file.
For a reported partial import, resolve the error and use its `--start-at` offset
with the unchanged source. This offset counts accepted (not restricted) entries.
## Security and limitations
Read [SECURITY.md](SECURITY.md) before storing sensitive project material.
Raw secrets and CONFIDENTIAL/SECRET records are not a supported memory workload.
This release deliberately does **not** provide a raw-secret retrieval tool or an
arbitrary-command secret broker. Use your existing credential manager for keys.
Redaction is defense in depth and cannot identify every possible secret.
MCP cannot see the full host conversation. Only explicitly supplied facts are
saved. Unsaved conversation and work after the last checkpoint cannot be
recovered. No current-file/git-state verification is claimed by a handoff.
Hosted/browser-only clients cannot open a local stdio MCP without a supported
local bridge. Grok compatibility depends on the specific client's MCP support.
## License and sponsorship
### MITライセンスと商用利用の事前相談
SafetyPack MCPのソースコードは [MITライセンス](LICENSE) で公開しています。
著作権表示とライセンス文の保持など、MITの条件に従って商用・非商用を問わず
利用・改変・再配布できます。別途ダウンロードするモデルや依存ライブラリには、
それぞれのライセンスが適用されます。
**商用利用をご検討の方は、導入前のご相談と、継続開発を支える協賛金への
ご協力をお願いいたします。** 個人利用の方からの任意の寄付・協賛も歓迎します。
ご相談先:**[monoqlo78@gmail.com](mailto:monoqlo78@gmail.com)**
事前相談・協賛・寄付はいずれも任意のお願いであり、MITライセンスに追加する
利用条件ではありません。相談や支払いの有無によって、MITで許諾された商用利用を
制限するものではありません。協賛によって保守対応や個別サポートが自動的に
付帯するものでもありません。
Commercial use is permitted under MIT. Advance consultation and sponsorship
are appreciated but **not required** to exercise the rights granted by MIT.
Voluntary contributions do not automatically include a support contract.
### 協賛金・寄付のお振込先
| 項目 | 内容 |
| --- | --- |
| 銀行名 | 三井住友銀行 |
| 支店名 | 東京営業部 |
| 支店コード(店番) | **211** |
| 口座番号 | **9602613** |
| 口座種別・口座名義 | お振込前に上記メール窓口へご確認ください |
支店コードは [三井住友銀行の公式店舗案内](https://www.e-map.ne.jp/smt/smbcbank/inf/2501010500200/)
の「同じ窓口で営業する店舗はこちら」で確認できます(2026年9月8日確認)。
本店営業部(店番200)と同じ窓口ですが、振込先は **東京営業部(211)** です。
振込先の名義・口座種別・番号を確認してからお手続きください。
### Bitcoinでの協賛・寄付
| 項目 | 内容 |
| --- | --- |
| 通貨 | Bitcoin(BTC) |
| ネットワーク | **Bitcoinメインネット(オンチェーン)** |
| 受取先 | 開発者指定のbitFlyer入金アドレス |
| アドレス | `3Fgu5zvE9Qwums7juNbhSqRK6pZ38T2U3i` |
BTC以外の通貨や別のネットワーク、Lightning経由では送金しないでください。
送金前に、上記メール窓口で最新の入金先と受取可否をご確認ください。
暗号資産の送金は通常取り消せないため、通貨・ネットワーク・アドレスを
十分に確認してください。銀行振込・Bitcoinともに金額は任意です。
## Development
```powershell
.\.venv-safetypack\Scripts\python.exe -m pip install --only-binary=:all: -e ".[test]"
.\.venv-safetypack\Scripts\python.exe -m pytest .\tests -q
```
The package uses pytest. Tests use temporary
stores and synthetic data, not the user's memory or API keys.
The original synthetic suite supplied calibration and a first held-out run.
That run exposed a wrong confident E5-only match, so it is now a **regression**
set, not untouched validation. `e5_only_v0_2.json` preserves that rejected design
and the replacement policy frozen before evaluating independently authored data:
```powershell
.\.venv-safetypack\Scripts\python.exe .\tests\evaluate_retrieval.py --mode lexical --split held-out
.\.venv-safetypack\Scripts\python.exe .\tests\evaluate_retrieval.py --mode hybrid --split held-out
.\.venv-safetypack\Scripts\python.exe .\tests\evaluate_retrieval.py --mode hybrid --dataset .\tests\fixtures\precision_holdout_v2.json --split held-out
```
Hybrid evaluation requires explicit model setup first. It never downloads a
model on its own. Metrics include abstention, irrelevant returned items,
ambiguity and incorrect confident matches, not just successful top-1 hits.
Independent cases were authored without access to the model implementation or
original fixtures. These small synthetic evaluations are not a guarantee of
accuracy on real project histories; semantic errors and missed evidence remain
possible. Set `SAFETYPACK_TEST_NEURAL=1` to include installed-model tests in pytest.
Normal CI never downloads models. A manually dispatched CI run can enable the
explicit `neural` option to install the pinned public bundles and exercise them
on Windows and Linux using synthetic data.
### Measured limitations, not deployment claims
The final relevance cutoff was selected on the original calibration set
(`-1.0` raw logit, margin `1.0`, at most 24 candidates). Margins include runners-up
below the admission cutoff. No threshold was tuned on the independent holdout.
The first-run results are preserved under `tests/fixtures/`:
| Dataset | Correct top-1 / answerable | Answerable abstentions | Unanswerable queries returning a record |
| --- | --- | --- | --- |
| Original calibration | 5 / 6 | 1 | 0 / 3 |
| Original regression questions | 7 / 12 | 5 | 0 / 6 |
| Independently authored holdout | 11 / 16 | 5 | 1 / 8 |
The known E5-only duplicate-write query incorrectly retrieved rollback; reranking
now retrieves the idempotency record. The independent holdout still exposed a
different limitation: a permissions record was retrieved for an approval-owner
question even though it did **not** identify an approver. That failure is retained,
not removed from the benchmark. It is why relevance and answer support are
explicitly separated in responses and client guidance. These are small synthetic
evaluations, not production adoption statistics or a guarantee against mistakes.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues