Metadata-Version: 2.5
Name: sagrada-mcp
Version: 0.3.1
Summary: Sagrada MCP server: track and verify reasoning state for AI systems via Model Context Protocol
Project-URL: Homepage, https://github.com/Cruxia-Labs/sagrada-mcp
Project-URL: Repository, https://github.com/Cruxia-Labs/sagrada-mcp
Project-URL: Issues, https://github.com/Cruxia-Labs/sagrada-mcp/issues
Author-email: Mars Ausili <mars@cruxia.ai>
License: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: agent-memory,claude,epistemic,mcp,model-context-protocol,provenance,reasoning
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: cryptography>=41
Requires-Dist: mcp<2.0.0,>=1.0.0
Requires-Dist: sagrada-engine>=0.3.0
Provides-Extra: crux
Provides-Extra: dev
Requires-Dist: build; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: twine; extra == 'dev'
Description-Content-Type: text/markdown

# sagrada-mcp

Model Context Protocol (MCP) server for Sagrada — track and verify reasoning
state for AI systems, and read attested repo-history records.

Sagrada gives Claude Code (and any MCP-capable client) durable,
content-addressed memory of design decisions, claim revisions, contradictions,
and the cryptographically verifiable chain of edits that produced the current
knowledge state.

## What this repository is

The source of the `sagrada-mcp` package on PyPI, so you can read what you
installed instead of taking our word for it.

The repo was created after 0.3.0 shipped. Its first commit is that release's
source, verbatim, tagged `v0.3.0` — so the code you install and the code you
read can be checked against each other:

```bash
pip download sagrada-mcp==0.3.0 --no-binary :all: --no-deps -d /tmp/pypi
tar xzf /tmp/pypi/sagrada_mcp-0.3.0.tar.gz -C /tmp
mkdir -p /tmp/tagged && git archive v0.3.0 | tar x -C /tmp/tagged
diff -r /tmp/tagged /tmp/sagrada_mcp-0.3.0 --exclude PKG-INFO   # no output
```

CI runs that diff on every push. **`main` is ahead of `v0.3.0`** and carries
unreleased work; `pip install sagrada-mcp` gives you the tag, not the branch.

What is *not* here: the compiled `sagrada` engine (Rust), which the 12
reasoning-tracker tools need. It installs from PyPI as `sagrada-engine`, and
its source is not published. The preflight gate — the part that refuses — is
in this repo, is pure Python, and does not depend on the engine.

## Installation

### Mode 1: pip install (clean venv, no repo checkout)

```bash
pip install sagrada-mcp
```

This installs the server plus vendored copies of its not-yet-published
dependencies (see `_vendor/README.md`). One server, **21 tools**:

- The 3 **preflight-gate tools** (`preflight_action`, `list_beliefs`,
  `verify_receipt`) gate consequential tool calls against the repo's typed
  beliefs and emit Ed25519-signed action receipts to
  `.sagrada/receipts.jsonl`, each independently verifiable offline with
  `uvx er1-verify` (1.0.1 or later — an unpinned install against a version
  constraint is a declared coverage gap the verifier recomputes, a receipt
  shape 1.0.0 predated). Deterministic and engine-free — refusal does not
  depend on the binary wheel.

  Receipts are signed with a keypair created **for your repo** on first use:
  the private half lives at `.sagrada/operator_key` (mode 0600 on POSIX,
  gitignored, never leaving your machine), the public half at `.sagrada/operator_key.pub`
  is meant to be committed. `verify_receipt` checks a receipt's signer against
  that committed key and the signed succession chain behind it, so a receipt
  from a key that was never this repo's comes back `foreign` rather than
  passing quietly. Earlier versions minted a key per process, which made every
  signature unpinnable — "signed by X" where X existed for one run.

  What that establishes is **continuity, not identity**: *if you pinned this
  repo's fingerprint out of band, and the private key has never left the
  machine, then a swap of the signing key shows up.* Each clause matters — a
  signature proves possession of a file, and files copy.

  For Claude Code there is also an ENFORCED layer: the `sagrada-preflight-hook`
  console script can be wired as a PreToolUse hook, and then blocks HALTed calls
  in-band. Installing the package does **not** register it — nothing here edits your
  Claude settings. You add it yourself; `preflight_hook.py` carries the exact
  one-line entry to paste.
- The 6 **repo-record (crux) tools** are fully functional given a `.crux`
  artifact (`SAGRADA_CRUX`). Without one they return a helpful error string.
- The 12 **reasoning-tracker tools** additionally need the compiled
  `sagrada-engine` wheel (a hard dependency as of 0.3.0; installed
  automatically on platforms with wheels). If the engine is somehow absent
  they return a clear JSON error naming the missing piece — never a
  traceback.

### Mode 2: from a clone of this repo

```bash
git clone https://github.com/Cruxia-Labs/sagrada-mcp && cd sagrada-mcp
pip install -e ".[dev]"
pytest -q
```

To run the server itself, note that it speaks MCP over stdio and **does not exit** — it
waits for a client, so run it from your MCP client's config rather than expecting a
prompt back:

```bash
python -m sagrada_mcp.server     # blocks; Ctrl-C to stop
```

The server prefers the real `sagrada_tracker` / `sagrada_preflight` packages
when they are importable and falls back to the copies in
`sagrada_mcp/_vendor/` otherwise — so it behaves identically here and in the
upstream tree those copies come from. In a clone the vendored copies are what
runs, and the test suite binds the same ones the server did
(`tests/conftest.py` prints which, in the pytest header).

## Configure in Claude Code / Claude Desktop

```json
{
  "mcpServers": {
    "sagrada": {
      "command": "sagrada-mcp",
      "env": { "SAGRADA_PROJECT": "/path/to/your/project" }
    }
  }
}
```

(In a repo checkout use `"command": "python", "args": ["-m", "sagrada_mcp.server"]`.)

## Tools provided (21)

### Preflight gate (3) — deterministic, no engine required

| Tool | Purpose |
|------|---------|
| `preflight_action` | Check a proposed tool call against the repo's typed beliefs; returns ALLOW or HALT with a signed receipt |
| `list_beliefs` | What the gate currently enforces, and which beliefs are HALT-eligible |
| `verify_receipt` | Re-verify a receipt: signature, recomputed verdict, and whether the signer is this repo's operator |

Recognition is a **finite, best-effort vocabulary**. The gate maps a tool call to
beliefs by reading the forms an agent actually emits — imports, package-manager
installs, deploy targets, env assignments. An action expressed in a form it does
not recognise is **not** mapped, and an unmapped action does not conflict with
anything, so it is ALLOWed. Treat HALT as an enforced policy check on recognised
actions, not as containment.

### Reasoning tracker (12) — require the compiled `sagrada` engine

| Tool | Purpose |
|------|---------|
| `track_decision` | Track a single design decision (auto-classifies as assert / refine / revise) |
| `track_from_text` | Extract and track decisions from free text |
| `ingest_text` | Ingest free text — auto-extracts claims, flags contradictions per claim |
| `query_decision` | Look up a tracked decision by term |
| `search_decisions` | Search decisions by term or definition |
| `get_decision_history` | Evolution history of a decision (or all) |
| `get_reasoning_status` | Full reasoning state summary |
| `check_coherence` | Report contradictions and coherence score |
| `check_consistency` | Read-only check whether new text contradicts existing knowledge (needs the optional ML battery for NLI) |
| `verify_chain` | Verify cryptographic integrity of the reasoning chain |
| `retract_decision` | Retract a previously tracked decision |
| `what_changed` | Prose summary of tracker-state changes since a record index (not a diff: each bucket is truncated to 5 names) |

### Repo-record / crux (6) — work anywhere, given a `.crux` artifact

Deterministic reads of a transformed repo-history record — no model, no
network, no clock. Every answer carries the record reference (artifact,
state_root, receipt) for offline verification.

| Tool | Purpose |
|------|---------|
| `repo_asof` | What value a tracked repo key held on a given date (with held-from/until evidence) |
| `what_replaced` | What value replaced a key's previous value, and when (flags retractions and comebacks) |
| `stale_rule_check` | List a tracked file's retired values and died-and-came-back values, with evidence |
| `crux_status` | The record being read: artifact, source HEAD, counts, state_root, receipt |
| `key_history` | Every recorded value of one tracked key, oldest first, with the record reference |
| `key_status` | Whether a tracked key is live, retired, or died-and-came-back |

**There is no public builder for `.crux` artifacts yet.** The reader is here and is
stdlib-only, so these six tools work fully against an artifact you already have — but the
tool that *builds* one is not in this repo and is not published. If you have no artifact,
each crux tool returns a pointer rather than failing, and until a builder ships that
pointer is the honest end of the road for a public user.

## Resources provided (3)

| Resource URI | Content |
|--------------|---------|
| `sagrada://state/summary` | Concise state summary for LLM context |
| `sagrada://state/decisions` | All tracked decisions |
| `sagrada://state/contradictions` | Currently-detected contradictions |

## Environment variables

| Variable | Purpose |
|----------|---------|
| `SAGRADA_PROJECT` | Path to the Sagrada project directory (auto-init if missing) |
| `SAGRADA_NO_ML` | Set to `true` to disable the ML classification battery (deterministic Jaccard floor instead) |
| `SAGRADA_BACKEND` | Persistence backend: `json_file` (default) or `sqlite` |
| `SAGRADA_CRUX` | Path to the `.crux` artifact the repo-record tools read (falls back to `results/*.crux` under `SAGRADA_PROJECT`) |

## License

Apache-2.0. Published by [Cruxia-Labs](https://github.com/Cruxia-Labs).
