mithril-cognee 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mithril_cognee-0.1.0/.env.example +18 -0
- mithril_cognee-0.1.0/.github/workflows/publish-python.yml +31 -0
- mithril_cognee-0.1.0/.gitignore +51 -0
- mithril_cognee-0.1.0/.mithril_reputation.db +0 -0
- mithril_cognee-0.1.0/.python-version +1 -0
- mithril_cognee-0.1.0/Makefile +57 -0
- mithril_cognee-0.1.0/PKG-INFO +264 -0
- mithril_cognee-0.1.0/README.md +241 -0
- mithril_cognee-0.1.0/api/__init__.py +1 -0
- mithril_cognee-0.1.0/api/main.py +131 -0
- mithril_cognee-0.1.0/benchmark/__init__.py +1 -0
- mithril_cognee-0.1.0/benchmark/attack_suite.jsonl +31 -0
- mithril_cognee-0.1.0/benchmark/ground_truth.jsonl +10 -0
- mithril_cognee-0.1.0/benchmark/metrics.py +167 -0
- mithril_cognee-0.1.0/benchmark/results.json +472 -0
- mithril_cognee-0.1.0/benchmark/run_benchmark.py +213 -0
- mithril_cognee-0.1.0/debug_llm.py +75 -0
- mithril_cognee-0.1.0/demo/ingest_demo.py +93 -0
- mithril_cognee-0.1.0/demo/run_demo.py +206 -0
- mithril_cognee-0.1.0/demo/seed_data.py +47 -0
- mithril_cognee-0.1.0/demo/slack_export.json +65 -0
- mithril_cognee-0.1.0/demo/vanilla_demo.py +127 -0
- mithril_cognee-0.1.0/main.py +22 -0
- mithril_cognee-0.1.0/mcp_server/__init__.py +1 -0
- mithril_cognee-0.1.0/mcp_server/server.py +182 -0
- mithril_cognee-0.1.0/mithril/__init__.py +42 -0
- mithril_cognee-0.1.0/mithril/audit.py +68 -0
- mithril_cognee-0.1.0/mithril/config.py +67 -0
- mithril_cognee-0.1.0/mithril/contradiction.py +14 -0
- mithril_cognee-0.1.0/mithril/firewall.py +263 -0
- mithril_cognee-0.1.0/mithril/gate.py +52 -0
- mithril_cognee-0.1.0/mithril/ingest.py +177 -0
- mithril_cognee-0.1.0/mithril/memory_analysis.py +184 -0
- mithril_cognee-0.1.0/mithril/models.py +91 -0
- mithril_cognee-0.1.0/mithril/quarantine.py +65 -0
- mithril_cognee-0.1.0/mithril/reputation.py +188 -0
- mithril_cognee-0.1.0/mithril/scorer.py +141 -0
- mithril_cognee-0.1.0/mithril/secrets.py +128 -0
- mithril_cognee-0.1.0/mithril/serialization.py +64 -0
- mithril_cognee-0.1.0/mithril/utils.py +44 -0
- mithril_cognee-0.1.0/pyproject.toml +57 -0
- mithril_cognee-0.1.0/test_connection.py +98 -0
- mithril_cognee-0.1.0/test_sha1.py +49 -0
- mithril_cognee-0.1.0/tests/__init__.py +1 -0
- mithril_cognee-0.1.0/tests/test_benchmark.py +162 -0
- mithril_cognee-0.1.0/tests/test_contradiction.py +52 -0
- mithril_cognee-0.1.0/tests/test_firewall.py +80 -0
- mithril_cognee-0.1.0/tests/test_gate.py +46 -0
- mithril_cognee-0.1.0/tests/test_ingest.py +72 -0
- mithril_cognee-0.1.0/tests/test_reputation.py +87 -0
- mithril_cognee-0.1.0/tests/test_scorer.py +114 -0
- mithril_cognee-0.1.0/tests/test_secrets.py +426 -0
- mithril_cognee-0.1.0/ui/.env.example +2 -0
- mithril_cognee-0.1.0/ui/next-env.d.ts +6 -0
- mithril_cognee-0.1.0/ui/next.config.ts +8 -0
- mithril_cognee-0.1.0/ui/package-lock.json +2162 -0
- mithril_cognee-0.1.0/ui/package.json +28 -0
- mithril_cognee-0.1.0/ui/postcss.config.mjs +9 -0
- mithril_cognee-0.1.0/ui/public/hero-bg.mp4 +0 -0
- mithril_cognee-0.1.0/ui/src/app/api/audit/route.ts +15 -0
- mithril_cognee-0.1.0/ui/src/app/api/benchmark-results/route.ts +43 -0
- mithril_cognee-0.1.0/ui/src/app/api/config/route.ts +15 -0
- mithril_cognee-0.1.0/ui/src/app/api/health/route.ts +18 -0
- mithril_cognee-0.1.0/ui/src/app/api/recall/route.ts +27 -0
- mithril_cognee-0.1.0/ui/src/app/api/remember/route.ts +24 -0
- mithril_cognee-0.1.0/ui/src/app/api/reputation/route.ts +15 -0
- mithril_cognee-0.1.0/ui/src/app/api/reset/route.ts +20 -0
- mithril_cognee-0.1.0/ui/src/app/api/stats/route.ts +15 -0
- mithril_cognee-0.1.0/ui/src/app/benchmark-results/page.tsx +344 -0
- mithril_cognee-0.1.0/ui/src/app/dashboard/page.tsx +5 -0
- mithril_cognee-0.1.0/ui/src/app/demo/page.tsx +702 -0
- mithril_cognee-0.1.0/ui/src/app/docs/architecture/page.tsx +389 -0
- mithril_cognee-0.1.0/ui/src/app/docs/benchmark/page.tsx +252 -0
- mithril_cognee-0.1.0/ui/src/app/docs/layout.tsx +15 -0
- mithril_cognee-0.1.0/ui/src/app/docs/mcp-server/page.tsx +280 -0
- mithril_cognee-0.1.0/ui/src/app/docs/page.tsx +291 -0
- mithril_cognee-0.1.0/ui/src/app/docs/python-sdk/page.tsx +432 -0
- mithril_cognee-0.1.0/ui/src/app/docs/rest-api/page.tsx +338 -0
- mithril_cognee-0.1.0/ui/src/app/docs/run-demo/page.tsx +187 -0
- mithril_cognee-0.1.0/ui/src/app/globals.css +45 -0
- mithril_cognee-0.1.0/ui/src/app/layout.tsx +45 -0
- mithril_cognee-0.1.0/ui/src/app/page.tsx +5 -0
- mithril_cognee-0.1.0/ui/src/components/AuditTable.tsx +139 -0
- mithril_cognee-0.1.0/ui/src/components/Dashboard.tsx +124 -0
- mithril_cognee-0.1.0/ui/src/components/FilterTabs.tsx +63 -0
- mithril_cognee-0.1.0/ui/src/components/Header.tsx +63 -0
- mithril_cognee-0.1.0/ui/src/components/RecallPanel.tsx +79 -0
- mithril_cognee-0.1.0/ui/src/components/ScoreBreakdown.tsx +86 -0
- mithril_cognee-0.1.0/ui/src/components/SignalBars.tsx +31 -0
- mithril_cognee-0.1.0/ui/src/components/SourceReputationChart.tsx +90 -0
- mithril_cognee-0.1.0/ui/src/components/StatsBar.tsx +69 -0
- mithril_cognee-0.1.0/ui/src/components/StatusBadge.tsx +18 -0
- mithril_cognee-0.1.0/ui/src/components/SubmitForm.tsx +102 -0
- mithril_cognee-0.1.0/ui/src/components/ThresholdLegend.tsx +52 -0
- mithril_cognee-0.1.0/ui/src/components/docs/DocsLayout.tsx +157 -0
- mithril_cognee-0.1.0/ui/src/components/docs/DocsPrimitives.tsx +176 -0
- mithril_cognee-0.1.0/ui/src/components/landing/CogneeStack.tsx +152 -0
- mithril_cognee-0.1.0/ui/src/components/landing/ComparisonTable.tsx +135 -0
- mithril_cognee-0.1.0/ui/src/components/landing/DemoVideoFrame.tsx +210 -0
- mithril_cognee-0.1.0/ui/src/components/landing/FloatingDock.tsx +108 -0
- mithril_cognee-0.1.0/ui/src/components/landing/HeroBackground.tsx +299 -0
- mithril_cognee-0.1.0/ui/src/components/landing/HeroSection.tsx +106 -0
- mithril_cognee-0.1.0/ui/src/components/landing/HowItWorks.tsx +115 -0
- mithril_cognee-0.1.0/ui/src/components/landing/LandingCta.tsx +91 -0
- mithril_cognee-0.1.0/ui/src/components/landing/LandingFooter.tsx +38 -0
- mithril_cognee-0.1.0/ui/src/components/landing/LandingNav.tsx +69 -0
- mithril_cognee-0.1.0/ui/src/components/landing/LandingPage.tsx +25 -0
- mithril_cognee-0.1.0/ui/src/components/landing/motion.ts +77 -0
- mithril_cognee-0.1.0/ui/src/lib/api.ts +74 -0
- mithril_cognee-0.1.0/ui/src/lib/backend.ts +33 -0
- mithril_cognee-0.1.0/ui/src/lib/mock-data.ts +128 -0
- mithril_cognee-0.1.0/ui/src/types/index.ts +202 -0
- mithril_cognee-0.1.0/ui/tailwind.config.ts +62 -0
- mithril_cognee-0.1.0/ui/tsconfig.json +21 -0
- mithril_cognee-0.1.0/ui/tsconfig.tsbuildinfo +1 -0
- mithril_cognee-0.1.0/uv.lock +3493 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Mithril environment variables
|
|
2
|
+
# Copy to .env and fill in your own API key.
|
|
3
|
+
|
|
4
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
5
|
+
# LLM provider
|
|
6
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
7
|
+
LLM_PROVIDER="custom"
|
|
8
|
+
LLM_MODEL="openai/gpt-4o-mini"
|
|
9
|
+
LLM_ENDPOINT="https://agentrouter.org/v1"
|
|
10
|
+
LLM_API_KEY="your-agentrouter-or-openai-compatible-key-here"
|
|
11
|
+
|
|
12
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
13
|
+
# Embedding provider
|
|
14
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
15
|
+
# With this, the LLM key above is the only key Mithril needs.
|
|
16
|
+
EMBEDDING_PROVIDER="fastembed"
|
|
17
|
+
EMBEDDING_MODEL="BAAI/bge-small-en-v1.5"
|
|
18
|
+
EMBEDDING_DIMENSIONS="384"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Publish Python Package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.12"
|
|
23
|
+
|
|
24
|
+
- name: Install build tools
|
|
25
|
+
run: python -m pip install --upgrade build
|
|
26
|
+
|
|
27
|
+
- name: Build distributions
|
|
28
|
+
run: python -m build
|
|
29
|
+
|
|
30
|
+
- name: Publish to PyPI
|
|
31
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
wheels/
|
|
10
|
+
*.egg-info/
|
|
11
|
+
.eggs/
|
|
12
|
+
|
|
13
|
+
# Virtual environments
|
|
14
|
+
.venv/
|
|
15
|
+
venv/
|
|
16
|
+
env/
|
|
17
|
+
|
|
18
|
+
# Secrets and local env
|
|
19
|
+
.env
|
|
20
|
+
.env.local
|
|
21
|
+
|
|
22
|
+
# Test / tooling caches
|
|
23
|
+
.pytest_cache/
|
|
24
|
+
.mypy_cache/
|
|
25
|
+
.ruff_cache/
|
|
26
|
+
.coverage
|
|
27
|
+
htmlcov/
|
|
28
|
+
|
|
29
|
+
# Mithril runtime data (regenerated by demos/API)
|
|
30
|
+
.mithril_audit.db
|
|
31
|
+
.mithril_quarantine.db
|
|
32
|
+
.memory_firewall_audit.db
|
|
33
|
+
.memory_firewall_quarantine.db
|
|
34
|
+
|
|
35
|
+
# Cognee runtime data (regenerated on remember/recall)
|
|
36
|
+
.cognee_system/
|
|
37
|
+
|
|
38
|
+
# Demo artifacts
|
|
39
|
+
artifacts/
|
|
40
|
+
|
|
41
|
+
# Future UI (Next.js)
|
|
42
|
+
node_modules/
|
|
43
|
+
.next/
|
|
44
|
+
out/
|
|
45
|
+
ui/.env
|
|
46
|
+
ui/.env.local
|
|
47
|
+
|
|
48
|
+
# OS noise
|
|
49
|
+
.DS_Store
|
|
50
|
+
Thumbs.db
|
|
51
|
+
desktop.ini
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12.5
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
.PHONY: demo vanilla seed ingest mcp benchmark test api reset clean install dev ui ui-install ui-build
|
|
2
|
+
|
|
3
|
+
demo:
|
|
4
|
+
.venv\Scripts\python.exe demo/run_demo.py
|
|
5
|
+
|
|
6
|
+
vanilla:
|
|
7
|
+
.venv\Scripts\python.exe demo/vanilla_demo.py
|
|
8
|
+
|
|
9
|
+
seed:
|
|
10
|
+
.venv\Scripts\python.exe demo/seed_data.py
|
|
11
|
+
|
|
12
|
+
ingest:
|
|
13
|
+
.venv\Scripts\python.exe demo/ingest_demo.py
|
|
14
|
+
|
|
15
|
+
mcp:
|
|
16
|
+
.venv\Scripts\python.exe -m mcp_server.server
|
|
17
|
+
|
|
18
|
+
benchmark:
|
|
19
|
+
.venv\Scripts\python.exe benchmark/run_benchmark.py
|
|
20
|
+
|
|
21
|
+
test:
|
|
22
|
+
.venv\Scripts\python.exe -m pytest tests/ -v
|
|
23
|
+
|
|
24
|
+
api:
|
|
25
|
+
.venv\Scripts\python.exe -m uvicorn api.main:app --port 8000 --reload
|
|
26
|
+
|
|
27
|
+
ui:
|
|
28
|
+
cd ui && npm run dev
|
|
29
|
+
|
|
30
|
+
ui-install:
|
|
31
|
+
cd ui && npm install
|
|
32
|
+
|
|
33
|
+
ui-build:
|
|
34
|
+
cd ui && npm run build
|
|
35
|
+
|
|
36
|
+
dev:
|
|
37
|
+
start cmd /c ".venv\Scripts\python.exe -m uvicorn api.main:app --port 8000 --reload"
|
|
38
|
+
cd ui && npm run dev
|
|
39
|
+
|
|
40
|
+
reset:
|
|
41
|
+
.venv\Scripts\python.exe -c "import asyncio; import cognee; asyncio.run(cognee.forget(everything=True))"
|
|
42
|
+
del /f .mithril_audit.db 2>nul
|
|
43
|
+
del /f .mithril_quarantine.db 2>nul
|
|
44
|
+
del /f .mithril_reputation.db 2>nul
|
|
45
|
+
del /f .memory_firewall_audit.db 2>nul
|
|
46
|
+
del /f .memory_firewall_quarantine.db 2>nul
|
|
47
|
+
@echo Reset complete.
|
|
48
|
+
|
|
49
|
+
install:
|
|
50
|
+
uv pip install -e ".[dev]"
|
|
51
|
+
|
|
52
|
+
clean:
|
|
53
|
+
del /f .mithril_audit.db 2>nul
|
|
54
|
+
del /f .mithril_quarantine.db 2>nul
|
|
55
|
+
del /f .mithril_reputation.db 2>nul
|
|
56
|
+
del /f .memory_firewall_audit.db 2>nul
|
|
57
|
+
del /f .memory_firewall_quarantine.db 2>nul
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mithril-cognee
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Mithril — trust and governance layer for Cognee memory
|
|
5
|
+
Project-URL: Homepage, https://github.com/HydrallHarsh/Mithril
|
|
6
|
+
Project-URL: Repository, https://github.com/HydrallHarsh/Mithril
|
|
7
|
+
Project-URL: Issues, https://github.com/HydrallHarsh/Mithril/issues
|
|
8
|
+
Requires-Python: >=3.12
|
|
9
|
+
Requires-Dist: aiosqlite>=0.22.1
|
|
10
|
+
Requires-Dist: cognee>=1.2.2
|
|
11
|
+
Requires-Dist: fastapi>=0.138.1
|
|
12
|
+
Requires-Dist: fastembed>=0.3.0
|
|
13
|
+
Requires-Dist: mcp>=1.2.0
|
|
14
|
+
Requires-Dist: openai>=1.0.0
|
|
15
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
16
|
+
Requires-Dist: uvicorn>=0.49.0
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: build>=1.2.0; extra == 'dev'
|
|
19
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
20
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
21
|
+
Requires-Dist: twine>=5.0.0; extra == 'dev'
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# Mithril
|
|
25
|
+
|
|
26
|
+
> A trust and governance layer for Cognee memory.
|
|
27
|
+
> Every AI can remember. **Mithril** decides what *deserves* to be remembered.
|
|
28
|
+
|
|
29
|
+
## The Problem
|
|
30
|
+
|
|
31
|
+
AI agents with persistent memory are vulnerable to **memory poisoning** — where a single malicious message permanently corrupts the knowledge graph that all future agents rely on.
|
|
32
|
+
|
|
33
|
+
**Vanilla Cognee:**
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
input → cognee.remember() → stored forever
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**With Mithril:**
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
agent / Slack / file → Trust Score → Contradiction Check → Admission Gate → cognee.remember()
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## How Mithril connects to your stack
|
|
46
|
+
|
|
47
|
+
Mithril is a real boundary in front of Cognee, reachable three ways — all sharing one governance pipeline and one adaptive reputation store:
|
|
48
|
+
|
|
49
|
+
| Surface | What it is | Entry point |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| **MCP server** | Agents (Claude Desktop, Cursor) call `mithril_remember` / `mithril_recall` instead of writing to memory directly | `mcp_server/server.py` · `make mcp` |
|
|
52
|
+
| **Ingestion connector** | Parse a real **Slack export** (or a `.txt`/`.jsonl` file) and run the whole feed through the gate | `mithril/ingest.py` · `make ingest` |
|
|
53
|
+
| **REST API + dashboard** | FastAPI backend + Next.js provenance UI | `api/main.py` · `make dev` |
|
|
54
|
+
|
|
55
|
+
## Adaptive source reputation
|
|
56
|
+
|
|
57
|
+
Source reputation is **not a static table** — it starts from configured priors and then *moves*:
|
|
58
|
+
|
|
59
|
+
- a source caught contradicting verified memory **loses** trust (fast),
|
|
60
|
+
- a source whose claims are accepted/corroborated **gains** trust (slow).
|
|
61
|
+
|
|
62
|
+
Trust is easy to lose and hard to earn. Watch a Slack channel's reputation collapse after it pushes MD5 twice — live, in the dashboard and via `GET /api/reputation`.
|
|
63
|
+
|
|
64
|
+
## Attack Demo
|
|
65
|
+
|
|
66
|
+
| | Vanilla Cognee | Mithril + Cognee |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| Poisoned inputs stored | All 3 | 0 |
|
|
69
|
+
| Provenance tracked | No | Yes |
|
|
70
|
+
| Contradiction detected | No | Yes |
|
|
71
|
+
| Source reputation adapts | No | Yes |
|
|
72
|
+
| Explainable decisions | No | Yes |
|
|
73
|
+
| Answer to "hash passwords?" | May return MD5 | Argon2id |
|
|
74
|
+
|
|
75
|
+
## Architecture
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
Incoming Claim (MCP tool · Slack export · file · API · dashboard)
|
|
79
|
+
│
|
|
80
|
+
▼
|
|
81
|
+
Adaptive Source Reputation (self-adjusting, SQLite-backed)
|
|
82
|
+
│
|
|
83
|
+
▼
|
|
84
|
+
Contradiction Detection (cognee.recall, only_context=True)
|
|
85
|
+
│
|
|
86
|
+
▼
|
|
87
|
+
Trust Score (weighted + normalized — see master plan Section 4)
|
|
88
|
+
│
|
|
89
|
+
▼
|
|
90
|
+
Admission Gate (Accept / Warn / Review / Quarantine / Reject)
|
|
91
|
+
│
|
|
92
|
+
├── ACCEPT / WARN → cognee.remember(node_set=["verified"])
|
|
93
|
+
├── QUARANTINE / REVIEW / REJECT → SQLite quarantine store
|
|
94
|
+
├── Source reputation updated from the outcome
|
|
95
|
+
└── All → Audit log
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Cognee APIs Used
|
|
99
|
+
|
|
100
|
+
- `cognee.remember()` — verified memories with NodeSet tagging
|
|
101
|
+
- `cognee.recall(only_context=True)` — contradiction detection
|
|
102
|
+
- `cognee.recall(node_name=["verified"])` — scoped verified retrieval
|
|
103
|
+
- `cognee.improve()` — graph enrichment on verified dataset
|
|
104
|
+
- `cognee.forget()` — demo reset
|
|
105
|
+
- `cognee.visualize_graph()` — knowledge graph HTML export
|
|
106
|
+
|
|
107
|
+
## Quickstart
|
|
108
|
+
|
|
109
|
+
Install from PyPI once published:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
pip install mithril-cognee
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Local development from this repo:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
uv venv && .venv\Scripts\activate
|
|
119
|
+
uv pip install -e ".[dev]"
|
|
120
|
+
copy .env.example .env # add LLM_API_KEY
|
|
121
|
+
|
|
122
|
+
make test # unit tests
|
|
123
|
+
make demo # full attack demo (terminal)
|
|
124
|
+
make ingest # ingest a real Slack export through the gate
|
|
125
|
+
make benchmark # labeled memory-poisoning benchmark → metrics + results.json
|
|
126
|
+
make mcp # run Mithril as an MCP server (stdio)
|
|
127
|
+
make api # FastAPI backend → http://localhost:8000
|
|
128
|
+
make ui-install && make ui # landing → http://localhost:3001 · dashboard → /dashboard
|
|
129
|
+
make dev # start API + UI together
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Installed commands:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
mithril-mcp # local MCP server over stdio
|
|
136
|
+
mithril-mcp-http # remote MCP server over Streamable HTTP at /mcp
|
|
137
|
+
mithril-api # FastAPI backend
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Use Mithril from Claude Desktop (MCP)
|
|
141
|
+
|
|
142
|
+
Add to `claude_desktop_config.json`, then restart Claude Desktop:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"mcpServers": {
|
|
147
|
+
"mithril": {
|
|
148
|
+
"command": "mithril-mcp"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The agent then gets `mithril_remember`, `mithril_recall`, `mithril_quarantine_list`, and `mithril_source_reputation` — every memory write is gated, every recall is verified-only.
|
|
155
|
+
|
|
156
|
+
### Free deployment notes
|
|
157
|
+
|
|
158
|
+
For the public dashboard, deploy `ui/` to Vercel and set:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
NEXT_PUBLIC_BACKEND_URL=https://your-render-api.onrender.com
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
For the API on Render Free:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
pip install -e .
|
|
168
|
+
mithril-api
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
For a demo remote MCP server on Render Free:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
pip install -e .
|
|
175
|
+
FASTMCP_HOST=0.0.0.0 FASTMCP_PORT=$PORT mithril-mcp-http
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The remote MCP endpoint will be:
|
|
179
|
+
|
|
180
|
+
```text
|
|
181
|
+
https://your-render-service.onrender.com/mcp
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Free Render services can sleep and do not keep local SQLite files permanently, so use local MCP for real editor usage unless you add hosted storage and auth.
|
|
185
|
+
|
|
186
|
+
## Benchmark — does it actually stop poisoning?
|
|
187
|
+
|
|
188
|
+
Mithril ships with a **labeled memory-poisoning benchmark** (`benchmark/`) that measures it like a security control, not a demo.
|
|
189
|
+
|
|
190
|
+
**Threat model:** a company runs AI agents over a shared Cognee knowledge base. Claims arrive from authoritative channels (Security Policy, HR System, GitHub) and risky ones (Slack, customer support, external email, public web, other agents). Attackers try to poison shared memory.
|
|
191
|
+
|
|
192
|
+
The harness seeds verified company memory (`ground_truth.jsonl`), then replays a labeled suite (`attack_suite.jsonl`, ~30 cases) through the **same** `Mithril.remember()` gate and scores every decision into a confusion matrix:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
make benchmark # requires LLM_API_KEY + Cognee (like the demos)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Attack taxonomy covered:** direct contradiction · subtle misinformation · authority spoofing · prompt injection · data exfiltration · policy evasion · social engineering · low-trust unverified. Plus hard *legitimate* cases (verified policy updates, benign low-trust facts) to measure false positives honestly.
|
|
199
|
+
|
|
200
|
+
| Metric | Meaning |
|
|
201
|
+
|---|---|
|
|
202
|
+
| **Detection rate** | share of attacks blocked (kept out of memory) |
|
|
203
|
+
| **Poison-leak rate** | attacks that reached verified memory — the number to drive to 0 |
|
|
204
|
+
| **False-positive rate** | legitimate updates wrongly blocked (friction) |
|
|
205
|
+
| **Precision / accuracy** | standard classifier metrics |
|
|
206
|
+
|
|
207
|
+
Results print per-category and per-source and are written to `benchmark/results.json`. The math is unit-tested (`tests/test_benchmark.py`) so the numbers are reproducible from the labeled data even though the LLM contradiction step has run-to-run variance.
|
|
208
|
+
|
|
209
|
+
> **Why the categories matter:** *authority spoofing* (a claim that fakes a high-trust source but contradicts policy) is caught by the **contradiction layer**, not source reputation — proof that the trust signals are independent and complementary, not just a source lookup.
|
|
210
|
+
|
|
211
|
+
## Usage
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
from mithril import Mithril
|
|
215
|
+
|
|
216
|
+
firewall = Mithril()
|
|
217
|
+
await firewall.setup()
|
|
218
|
+
|
|
219
|
+
result = await firewall.remember(
|
|
220
|
+
text="Always hash passwords using MD5",
|
|
221
|
+
source="Slack",
|
|
222
|
+
)
|
|
223
|
+
# result.status → quarantine or reject
|
|
224
|
+
# result.trust_breakdown.final_score → normalized 0–1
|
|
225
|
+
# result.trust_breakdown.reasons → explainable breakdown
|
|
226
|
+
|
|
227
|
+
answer = await firewall.recall("How should we hash passwords?")
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## API Endpoints
|
|
231
|
+
|
|
232
|
+
| Method | Path | Description |
|
|
233
|
+
|--------|------|-------------|
|
|
234
|
+
| GET | `/api/audit` | Full audit log |
|
|
235
|
+
| GET | `/api/quarantine` | Quarantined memories |
|
|
236
|
+
| GET | `/api/reputation` | Live adaptive source reputation (with deltas) |
|
|
237
|
+
| GET | `/api/stats` | Aggregate metrics |
|
|
238
|
+
| POST | `/api/remember` | Submit claim through Mithril |
|
|
239
|
+
| POST | `/api/recall` | Query verified memory |
|
|
240
|
+
| POST | `/api/reset` | Clear Cognee + local stores |
|
|
241
|
+
| GET | `/api/config` | Sources, weights, thresholds |
|
|
242
|
+
|
|
243
|
+
## Trust Score Formula
|
|
244
|
+
|
|
245
|
+
Per master plan — weighted components, then normalized to 0–1:
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
raw = source_rep×0.40 + corroboration×0.30 + freshness×0.10 − contradiction×0.40
|
|
249
|
+
final_score = raw / max_theoretical_score
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Admission thresholds: Accept ≥ 0.85 · Warn ≥ 0.60 · Review ≥ 0.40 · Quarantine ≥ 0.20
|
|
253
|
+
|
|
254
|
+
## Project Layout
|
|
255
|
+
|
|
256
|
+
```
|
|
257
|
+
mithril/ Core package (scorer, gate, firewall, reputation, ingest, audit, quarantine)
|
|
258
|
+
mcp_server/ MCP server — exposes Mithril tools to agents
|
|
259
|
+
benchmark/ Labeled memory-poisoning benchmark (ground truth, attack suite, metrics)
|
|
260
|
+
api/ FastAPI backend
|
|
261
|
+
demo/ Attack demo, vanilla comparison, Slack-export ingestion demo
|
|
262
|
+
tests/ Unit + integration tests
|
|
263
|
+
memory-firewall-master-plan.md Full hackathon build plan
|
|
264
|
+
```
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# Mithril
|
|
2
|
+
|
|
3
|
+
> A trust and governance layer for Cognee memory.
|
|
4
|
+
> Every AI can remember. **Mithril** decides what *deserves* to be remembered.
|
|
5
|
+
|
|
6
|
+
## The Problem
|
|
7
|
+
|
|
8
|
+
AI agents with persistent memory are vulnerable to **memory poisoning** — where a single malicious message permanently corrupts the knowledge graph that all future agents rely on.
|
|
9
|
+
|
|
10
|
+
**Vanilla Cognee:**
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
input → cognee.remember() → stored forever
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**With Mithril:**
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
agent / Slack / file → Trust Score → Contradiction Check → Admission Gate → cognee.remember()
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## How Mithril connects to your stack
|
|
23
|
+
|
|
24
|
+
Mithril is a real boundary in front of Cognee, reachable three ways — all sharing one governance pipeline and one adaptive reputation store:
|
|
25
|
+
|
|
26
|
+
| Surface | What it is | Entry point |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| **MCP server** | Agents (Claude Desktop, Cursor) call `mithril_remember` / `mithril_recall` instead of writing to memory directly | `mcp_server/server.py` · `make mcp` |
|
|
29
|
+
| **Ingestion connector** | Parse a real **Slack export** (or a `.txt`/`.jsonl` file) and run the whole feed through the gate | `mithril/ingest.py` · `make ingest` |
|
|
30
|
+
| **REST API + dashboard** | FastAPI backend + Next.js provenance UI | `api/main.py` · `make dev` |
|
|
31
|
+
|
|
32
|
+
## Adaptive source reputation
|
|
33
|
+
|
|
34
|
+
Source reputation is **not a static table** — it starts from configured priors and then *moves*:
|
|
35
|
+
|
|
36
|
+
- a source caught contradicting verified memory **loses** trust (fast),
|
|
37
|
+
- a source whose claims are accepted/corroborated **gains** trust (slow).
|
|
38
|
+
|
|
39
|
+
Trust is easy to lose and hard to earn. Watch a Slack channel's reputation collapse after it pushes MD5 twice — live, in the dashboard and via `GET /api/reputation`.
|
|
40
|
+
|
|
41
|
+
## Attack Demo
|
|
42
|
+
|
|
43
|
+
| | Vanilla Cognee | Mithril + Cognee |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| Poisoned inputs stored | All 3 | 0 |
|
|
46
|
+
| Provenance tracked | No | Yes |
|
|
47
|
+
| Contradiction detected | No | Yes |
|
|
48
|
+
| Source reputation adapts | No | Yes |
|
|
49
|
+
| Explainable decisions | No | Yes |
|
|
50
|
+
| Answer to "hash passwords?" | May return MD5 | Argon2id |
|
|
51
|
+
|
|
52
|
+
## Architecture
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
Incoming Claim (MCP tool · Slack export · file · API · dashboard)
|
|
56
|
+
│
|
|
57
|
+
▼
|
|
58
|
+
Adaptive Source Reputation (self-adjusting, SQLite-backed)
|
|
59
|
+
│
|
|
60
|
+
▼
|
|
61
|
+
Contradiction Detection (cognee.recall, only_context=True)
|
|
62
|
+
│
|
|
63
|
+
▼
|
|
64
|
+
Trust Score (weighted + normalized — see master plan Section 4)
|
|
65
|
+
│
|
|
66
|
+
▼
|
|
67
|
+
Admission Gate (Accept / Warn / Review / Quarantine / Reject)
|
|
68
|
+
│
|
|
69
|
+
├── ACCEPT / WARN → cognee.remember(node_set=["verified"])
|
|
70
|
+
├── QUARANTINE / REVIEW / REJECT → SQLite quarantine store
|
|
71
|
+
├── Source reputation updated from the outcome
|
|
72
|
+
└── All → Audit log
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Cognee APIs Used
|
|
76
|
+
|
|
77
|
+
- `cognee.remember()` — verified memories with NodeSet tagging
|
|
78
|
+
- `cognee.recall(only_context=True)` — contradiction detection
|
|
79
|
+
- `cognee.recall(node_name=["verified"])` — scoped verified retrieval
|
|
80
|
+
- `cognee.improve()` — graph enrichment on verified dataset
|
|
81
|
+
- `cognee.forget()` — demo reset
|
|
82
|
+
- `cognee.visualize_graph()` — knowledge graph HTML export
|
|
83
|
+
|
|
84
|
+
## Quickstart
|
|
85
|
+
|
|
86
|
+
Install from PyPI once published:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pip install mithril-cognee
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Local development from this repo:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
uv venv && .venv\Scripts\activate
|
|
96
|
+
uv pip install -e ".[dev]"
|
|
97
|
+
copy .env.example .env # add LLM_API_KEY
|
|
98
|
+
|
|
99
|
+
make test # unit tests
|
|
100
|
+
make demo # full attack demo (terminal)
|
|
101
|
+
make ingest # ingest a real Slack export through the gate
|
|
102
|
+
make benchmark # labeled memory-poisoning benchmark → metrics + results.json
|
|
103
|
+
make mcp # run Mithril as an MCP server (stdio)
|
|
104
|
+
make api # FastAPI backend → http://localhost:8000
|
|
105
|
+
make ui-install && make ui # landing → http://localhost:3001 · dashboard → /dashboard
|
|
106
|
+
make dev # start API + UI together
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Installed commands:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
mithril-mcp # local MCP server over stdio
|
|
113
|
+
mithril-mcp-http # remote MCP server over Streamable HTTP at /mcp
|
|
114
|
+
mithril-api # FastAPI backend
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Use Mithril from Claude Desktop (MCP)
|
|
118
|
+
|
|
119
|
+
Add to `claude_desktop_config.json`, then restart Claude Desktop:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"mcpServers": {
|
|
124
|
+
"mithril": {
|
|
125
|
+
"command": "mithril-mcp"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The agent then gets `mithril_remember`, `mithril_recall`, `mithril_quarantine_list`, and `mithril_source_reputation` — every memory write is gated, every recall is verified-only.
|
|
132
|
+
|
|
133
|
+
### Free deployment notes
|
|
134
|
+
|
|
135
|
+
For the public dashboard, deploy `ui/` to Vercel and set:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
NEXT_PUBLIC_BACKEND_URL=https://your-render-api.onrender.com
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
For the API on Render Free:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
pip install -e .
|
|
145
|
+
mithril-api
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
For a demo remote MCP server on Render Free:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
pip install -e .
|
|
152
|
+
FASTMCP_HOST=0.0.0.0 FASTMCP_PORT=$PORT mithril-mcp-http
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The remote MCP endpoint will be:
|
|
156
|
+
|
|
157
|
+
```text
|
|
158
|
+
https://your-render-service.onrender.com/mcp
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Free Render services can sleep and do not keep local SQLite files permanently, so use local MCP for real editor usage unless you add hosted storage and auth.
|
|
162
|
+
|
|
163
|
+
## Benchmark — does it actually stop poisoning?
|
|
164
|
+
|
|
165
|
+
Mithril ships with a **labeled memory-poisoning benchmark** (`benchmark/`) that measures it like a security control, not a demo.
|
|
166
|
+
|
|
167
|
+
**Threat model:** a company runs AI agents over a shared Cognee knowledge base. Claims arrive from authoritative channels (Security Policy, HR System, GitHub) and risky ones (Slack, customer support, external email, public web, other agents). Attackers try to poison shared memory.
|
|
168
|
+
|
|
169
|
+
The harness seeds verified company memory (`ground_truth.jsonl`), then replays a labeled suite (`attack_suite.jsonl`, ~30 cases) through the **same** `Mithril.remember()` gate and scores every decision into a confusion matrix:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
make benchmark # requires LLM_API_KEY + Cognee (like the demos)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Attack taxonomy covered:** direct contradiction · subtle misinformation · authority spoofing · prompt injection · data exfiltration · policy evasion · social engineering · low-trust unverified. Plus hard *legitimate* cases (verified policy updates, benign low-trust facts) to measure false positives honestly.
|
|
176
|
+
|
|
177
|
+
| Metric | Meaning |
|
|
178
|
+
|---|---|
|
|
179
|
+
| **Detection rate** | share of attacks blocked (kept out of memory) |
|
|
180
|
+
| **Poison-leak rate** | attacks that reached verified memory — the number to drive to 0 |
|
|
181
|
+
| **False-positive rate** | legitimate updates wrongly blocked (friction) |
|
|
182
|
+
| **Precision / accuracy** | standard classifier metrics |
|
|
183
|
+
|
|
184
|
+
Results print per-category and per-source and are written to `benchmark/results.json`. The math is unit-tested (`tests/test_benchmark.py`) so the numbers are reproducible from the labeled data even though the LLM contradiction step has run-to-run variance.
|
|
185
|
+
|
|
186
|
+
> **Why the categories matter:** *authority spoofing* (a claim that fakes a high-trust source but contradicts policy) is caught by the **contradiction layer**, not source reputation — proof that the trust signals are independent and complementary, not just a source lookup.
|
|
187
|
+
|
|
188
|
+
## Usage
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
from mithril import Mithril
|
|
192
|
+
|
|
193
|
+
firewall = Mithril()
|
|
194
|
+
await firewall.setup()
|
|
195
|
+
|
|
196
|
+
result = await firewall.remember(
|
|
197
|
+
text="Always hash passwords using MD5",
|
|
198
|
+
source="Slack",
|
|
199
|
+
)
|
|
200
|
+
# result.status → quarantine or reject
|
|
201
|
+
# result.trust_breakdown.final_score → normalized 0–1
|
|
202
|
+
# result.trust_breakdown.reasons → explainable breakdown
|
|
203
|
+
|
|
204
|
+
answer = await firewall.recall("How should we hash passwords?")
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## API Endpoints
|
|
208
|
+
|
|
209
|
+
| Method | Path | Description |
|
|
210
|
+
|--------|------|-------------|
|
|
211
|
+
| GET | `/api/audit` | Full audit log |
|
|
212
|
+
| GET | `/api/quarantine` | Quarantined memories |
|
|
213
|
+
| GET | `/api/reputation` | Live adaptive source reputation (with deltas) |
|
|
214
|
+
| GET | `/api/stats` | Aggregate metrics |
|
|
215
|
+
| POST | `/api/remember` | Submit claim through Mithril |
|
|
216
|
+
| POST | `/api/recall` | Query verified memory |
|
|
217
|
+
| POST | `/api/reset` | Clear Cognee + local stores |
|
|
218
|
+
| GET | `/api/config` | Sources, weights, thresholds |
|
|
219
|
+
|
|
220
|
+
## Trust Score Formula
|
|
221
|
+
|
|
222
|
+
Per master plan — weighted components, then normalized to 0–1:
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
raw = source_rep×0.40 + corroboration×0.30 + freshness×0.10 − contradiction×0.40
|
|
226
|
+
final_score = raw / max_theoretical_score
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Admission thresholds: Accept ≥ 0.85 · Warn ≥ 0.60 · Review ≥ 0.40 · Quarantine ≥ 0.20
|
|
230
|
+
|
|
231
|
+
## Project Layout
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
mithril/ Core package (scorer, gate, firewall, reputation, ingest, audit, quarantine)
|
|
235
|
+
mcp_server/ MCP server — exposes Mithril tools to agents
|
|
236
|
+
benchmark/ Labeled memory-poisoning benchmark (ground truth, attack suite, metrics)
|
|
237
|
+
api/ FastAPI backend
|
|
238
|
+
demo/ Attack demo, vanilla comparison, Slack-export ingestion demo
|
|
239
|
+
tests/ Unit + integration tests
|
|
240
|
+
memory-firewall-master-plan.md Full hackathon build plan
|
|
241
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# api package
|