Atlas / MCP servers / rolandpg / Zettelforge

ZettelforgeBLOCK

mcp/rolandpg/zettelforge

Agentic memory for CTI in Python — STIX knowledge graphs, threat-actor alias resolution, offline-first RAG, MCP server for Claude Code and LangChain agents

Verdict
BLOCK
Grade
D
Trust score
66 /100
Exposed tools
—
Transport
stdio
License
MIT
Stars
64
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

The only agentic memory system built for cyber threat intelligence.

When a senior analyst leaves, two or three years of context walks out with them — customer environments, prior investigations, actor TTPs, false-positive patterns, every hard-won "wait, we've seen this before." ZettelForge is an agentic memory system built so that context stays with the team.

It extracts CVEs, threat actors, IOCs, and ATT&CK techniques from analyst notes and threat reports, resolves aliases (APT28 = Fancy Bear = STRONTIUM = Sofacy), builds a STIX 2.1 knowledge graph, and serves every past investigation back to your analysts — and to Claude Code via MCP — in natural language. Runs entirely in-process. No API keys. No cloud. No data leaves the host.

[](https://pypi.org/project/zettelforge/) [](https://pepy.tech/projects/zettelforge) [](https://star-history.com/#rolandpg/zettelforge&Date) [](https://www.python.org/downloads/) [](https://opensource.org/licenses/MIT) [](https://github.com/rolandpg/zettelforge/actions) [](https://github.com/rolandpg/zettelforge/issues) [](https://deepwiki.com/ThreatRecall/zettelforge)

**Star · `pip install zettelforge` · Docs ·

Read from source at commit 46594f0ec11bOBSERVED · 2026-10-08
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code (pypi)
claude mcp add zettelforge -- None zettelforge==2.4.0
03

Trust audit

BLOCKgrade D · trust 66/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryWARN
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)FAIL
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (2 observation(s))
Network
declared (8 observation(s))
Shell
none-observed
Dependencies
pinned
Secrets in source
found

Findings (25)

HIGHPrompt injection · prompt.override · CWE-94, CWE-1427
docs/reference/governance-controls.md:141
| Role rewrite | "you are now", "developer mode", jailbreak framing |
Why it matters. asks the agent to drop prior instructions or safety
Fix. remove the instruction
MEDIUMInventory / provenance · inv.binary · CWE-1104
web/ui/fonts/Neuropol.otf
Neuropol.otf
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
src/zettelforge/prompt_injection_guard.py:57
r"\b(reveal|print|dump|show|exfiltrate|leak|return)\b.{0,80}"
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
config.default.yaml:109
#   url: http://127.0.0.1:11434
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
config.default.yaml:115
#   url: http://127.0.0.1:11434
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
config.default.yaml:139
url: http://127.0.0.1:11434
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
config.example.yaml:26
#   url: http://127.0.0.1:11434
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
config.example.yaml:42
#   url: http://127.0.0.1:11434
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/test_telemetry_collector.py:164
secret = "SECRET_CONTENT_DO_NOT_LEAK"
LOWInventory / provenance · inv.binary · CWE-1104
docs/stylesheets/fonts/Neuropol.otf
Neuropol.otf
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
benchmarks/naive_memory.py:18
h = int(hashlib.md5(text.encode()).hexdigest(), 16)
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
src/zettelforge/memory_defense.py:44
key = (hashlib.sha1(text.encode(), usedforsecurity=False).hexdigest(), int(ngram_size))
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
src/zettelforge/synthesis_generator.py:86
"query_id": hashlib.md5(query.encode(), usedforsecurity=False).hexdigest()[:12],
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
src/zettelforge/vector_memory.py:187
h = int(hashlib.md5(text.encode(), usedforsecurity=False).hexdigest(), 16)
LOWNetwork egress · net.beacon_words · CWE-200, CWE-319
benchmarks/cti_retrieval_benchmark.py:52
"content": """Scattered Spider (also known as UNC3944 or Octo Tempest) is a financially motivated threat group known for social engineering attacks against large enterprises. The group specializes in
LOWNetwork egress · net.beacon_words · CWE-200, CWE-319
docs/assets/cf-analytics.js:6
s.src = 'https://static.cloudflareinsights.com/beacon.min.js';
LOWNetwork egress · net.beacon_words · CWE-200, CWE-319
docs/assets/cf-analytics.js:7
s.setAttribute('data-cf-beacon', '{"token": "7740fa0d6ecf41abb3c7bc06803e7ed3"}');
LOWNetwork egress · net.beacon_words · CWE-200, CWE-319
tests/test_detection_rule_entities.py:55
title="Cobalt Strike Beacon",
LOWPrompt injection · prompt.override · CWE-94, CWE-1427
docs/reference/governance-controls.md:140
| Instruction override | "ignore previous instructions", "override system rules" |
Why it matters. asks the agent to drop prior instructions or safety
Fix. remove the instruction
LOWPrompt injection · prompt.override · CWE-94, CWE-1427
docs/rfcs/RFC-017-memsad-write-time-defenses.md:144
- suspicious instruction phrases such as "ignore previous", "system prompt",
Why it matters. asks the agent to drop prior instructions or safety
Fix. remove the instruction
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
benchmarks/results/benchmark_report.md:1
# A-MEM Benchmark Report\n\n## Ingestion Performance\n- A-MEM: 7.037s\n- Naive Vector Memory: 0.007s\n\n## Query Performance\n\n### Query: What malware does APT28 use?\n**Expected Logic:** APT28 is Fa
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
docs/reference/configuration.md:184
**Operational impact.** Causal extraction at 8000 tokens runs 60–140 s per call on a 9B-Q4_K_M reasoning model; `remember(sync=True)` therefore blocks 1–3 minutes per note. The default async path (bac
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
docs/reference/configuration.md:637
**14 config sections** exist: `storage` (data directory), `typedb` (Enterprise TypeDB connection parameters), `backend` (community default: sqlite), `embedding` (vector model and server), `llm` (langu
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWInventory / provenance · mcp.no_tools_extracted · CWE-1104
server.json
Why it matters. the tool list is enumerated at runtime by tools/list, not declared in source
Fix. the page says so rather than showing an empty table
INFOInventory / provenance · inv.oversize · CWE-1104
benchmarks/enterprise-attack.json
benchmarks/enterprise-attack.json
Why it matters. 45126961 bytes not read

Gates applied: instruction_override, no_behavioural_pass.

Audited 2026-10-08 · audit v0.4.1 · source sha 46594f0ec11bfull audit observations/trust-audit/mcp-server/rolandpg__zettelforge.json · Report an issue / request a re-scan
04

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-0846594f0ec11bBLOCKD66first audit
05

Questions

What is the Zettelforge MCP server?

Agentic memory for CTI in Python — STIX knowledge graphs, threat-actor alias resolution, offline-first RAG, MCP server for Claude Code and LangChain agents

Is Zettelforge safe to connect to an agent?

No — not without reading the findings first. The audit graded it D (66/100) and found 1 critical or high issue in the source. Each one is listed on this page with the file and line it is on.

What credentials does Zettelforge need?

It reads OPENCTI_TOKEN, THREATENGRAM_LICENSE_KEY, TYPEDB_PASSWORD, ZETTELFORGE_LLM_API_KEY and ZETTELFORGE_WEB_API_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does Zettelforge run?

It speaks stdio, so it runs as a local process your client starts. It is published on PyPI as zettelforge.

How current is this page?

The grade is for one exact copy of the source (46594f0ec11b), read on 2026-10-08. The repository is watched and re-audited when it changes.

Advertisement