Install
$ agentstack add mcp-rohansx-ctxgraph ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
ctxgraph
Typed knowledge graph for AI agents. Single Rust binary. Single SQLite file. One LLM call per write. Zero LLM calls for 90% of reads.
brew install rohansx/tap/ctxgraph
ctxgraph init
ctxgraph log "Migrated auth from Redis sessions to JWT. Chose JWT for stateless scaling."
ctxgraph query "why did we move away from Redis?"
> Working spec: [docs/CLARITY.md](docs/CLARITY.md) — product, decisions, the 5 pieces to build, launch pitch. > Architecture: [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — as-built (§1-4) + v0.3 target (§5-14). > Roadmap: [docs/ROADMAP.md](docs/ROADMAP.md) — 5 pieces + 12-week schedule + this-weekend todo. > Benchmarks: [docs/BENCHMARKS.md](docs/BENCHMARKS.md) — measured F1 numbers + hostile-reader audit.
Benchmarks (measured, third-party + reproducible)
> Correction (2026-06): an earlier headline here claimed "+0.227 combined F1 over Graphiti." That was a measurement bug — an un-scoped Graphiti relation query (LIMIT 50, no group_id) scored Graphiti against the whole accumulating graph. Fixed. The honest picture: extraction quality is at parity with Graphiti and with cloud frontier models; the win is architectural — one LLM call, fully local, $0. Full detail + audit in [docs/BENCHMARKS.md](docs/BENCHMARKS.md).
Third-party accuracy — CoNLL04 (standard RE dataset neither tool authored), strict directional + typed relation scorer, 80 test sentences, single call. Reproduce: scripts/conll04_bench.py.
| Model (single call) | entity F1 | relation F1 (directional + typed) | |---|---|---| | anthropic/claude-haiku-4.5 | 0.864 | 0.604 | | z-ai/glm-5.2 | 0.867 | 0.589 | | google/gemini-2.5-flash-lite | 0.846 | 0.560 | | minimax/minimax-m3 | 0.840 | 0.541 | | deepseek/deepseek-v4-flash | 0.844 | 0.525 | | deepseek/deepseek-v3.2 | 0.861 | 0.514 |
vs Graphiti — same model (gemini-2.5-flash-lite), same fixture, same scorer (after fixing the bug): combined F1 0.638 (ctxgraph) vs 0.636 (Graphiti) — a statistical tie on extraction. The real, measured advantage is efficiency:
| | LLM calls / episode (measured) | local Gemma-4-12B latency | |---|---|---| | ctxgraph | 1.0 | ~33 s/ep | | Graphiti | 2.55 | ~84 s/ep |
→ equivalent extraction quality at ~2.6× fewer LLM calls, fully local, $0 marginal cost. That — not an accuracy edge — is the moat.
How it works
┌──────────────────────────────────────┐
│ WRITE PATH (one LLM call) │
│ Tier 1: GLiNER2 ONNX (CPU, ~30ms) │
│ Tier 2: NuExtract 2.0 (local Ollama) │
│ Tier 3: Cloud (only if needed) │
│ Mode B default: Cerebras free │
│ Paid: DeepInfra Gemma-4-26B-A4B │
└──────────────────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ SQLite + FTS5 + sqlite-vec │
│ bi-temporal edges, RRF search │
└──────────────────────────────────────┘
▲
│
┌──────────────────────────────────────┐
│ READ PATH (zero LLM in 90% cases) │
│ Simple (90%): │
│ verb → typed relation via cosine │
│ embedding match (~30 LOC) │
│ then deterministic SQL │
│ Complex (10%): │
│ local Qwen3-1.5B parses NL → │
│ graph op, then SQL │
│ NO cloud LLM ever in read path │
└──────────────────────────────────────┘
Two architectural bets:
- One LLM call per write. Tiered escalation: local ONNX handles ~70% of episodes, local LLM another 25%, cloud only when both fail. Compare to Graphiti's 6 calls per episode.
- Zero LLM calls in the read path for 90% of queries. The universal schema's 10 typed relations are a closed set — your user verb cosine-matches to one of them, then SQL runs deterministically. Only multi-hop / time-filter / conjunction queries (~10%) call a tiny local Qwen3-1.5B. No cloud LLM ever sees a read.
This is the bit competitors can't match. Graphiti, Mem0, Letta all need an LLM at read time because their relation types are free-form text the SQL engine can't reason about.
The universal schema (v0.3 target)
9 entity types, 10 relations, hardcoded. Users never write a schema.
| Entity types | Relation types | |---|---| | Person, Place, Organization, Concept, Artifact, Event, Time, Idea, Fact | mentions, locatedat, relatedto, caused, preceded, references, ownedby, partof, dependson, participatedin |
Broad enough to handle personal wikis, work notes, research, recipes, code, journal entries — anything text-shaped. Edge-case domains (recipes need "Ingredient", scientific datasets need "Measurement") get handled by an automatic schema-improvement loop: the LLM logs suggestions to a side-table; a nightly cron promotes types that show up across ≥ 5 distinct episodes with cosine-similarity /gemma-gguf:Q4KM' \ --base-url http://localhost:11434/v1/chat/completions --out conll04_local.json --limit 40
2) Cross-domain model bake-off (ctxgraph single-call prompt)
python scripts/openrouterbench.py --model deepseek/deepseek-v3.2 --out bench.json \ --skip-tech --cd-fixture crates/ctxgraph-extract/tests/fixtures/crossdomain_v2.json
3) ctxgraph-vs-Graphiti, same model, same scorer (needs Neo4j + graphiti venv)
docker run -d --name neo4j-bench -p 7687:7687 -e NEO4JAUTH=neo4j/benchpass123 neo4j:5.26 python3 -m venv .venv-graphiti && .venv-graphiti/bin/pip install graphiti-core neo4j fastembed .venv-graphiti/bin/python scripts/graphitiopenrouter_bench.py \ --model google/gemini-2.5-flash-lite --out graphiti.json
4) Cost/efficiency: measure Graphiti's ACTUAL LLM calls/episode vs ctxgraph's 1
.venv-graphiti/bin/python scripts/costefficiencybench.py --model google/gemini-2.5-flash-lite
Each model run costs ~$0.005–0.02 on OpenRouter; the CoNLL04 dataset is fetched
from HuggingFace at run time (no third-party data committed to the repo).
## Contributing
See [`CONTRIBUTING.md`](CONTRIBUTING.md). For design discussions, [`docs/CLARITY.md`](docs/CLARITY.md) is the working doc — propose changes against it.
## License
MIT
## Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [rohansx](https://github.com/rohansx)
- **Source:** [rohansx/ctxgraph](https://github.com/rohansx/ctxgraph)
- **License:** MIT
- **Homepage:** https://ctxgraph.io
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.