Mcp knowledge graph
Skill spideynolove/claude-code-in-action/05-subagents/.claude/skills/mcp-knowledge-graph
The process I experienced firsthand through the https://anthropic.skilljar.com/claude-code-in-action course using real-world daily projects
npx -y skills add spideynolove/claude-code-in-action --skill mcp-knowledge-graphAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.4 KB, as published. Nobody here has run it
mcp-knowledge-graph — Persistent Codebase Knowledge
When to invoke
Use this skill when:
- Starting work on a codebase you want to remember across sessions
- Extracting and persisting architectural facts (components, dependencies, decisions)
- Building a project knowledge graph from a repomix-packed codebase
- Querying previously stored architectural context instead of re-reading files
Do not use for: general conversation memory (use episodic-memory), temporary session notes, or storing raw code (store facts about code, not the code itself).
The combo workflow: repomix → analyze → knowledge-graph
1. repomix.pack_codebase() ← get full codebase content
2. grep/read the output ← extract architectural facts
3. aim_memory_store() ← persist entities (components, modules, services)
4. aim_memory_link() ← persist relations (depends_on, calls, owns)
5. aim_memory_add_facts() ← add observations to existing entities
In subsequent sessions: skip steps 1-2, query directly:
6. aim_memory_search("auth") ← find relevant entities by keyword
7. aim_memory_get(["AuthService"]) ← exact lookup of known entity
This saves repacking the entire codebase every session — the graph acts as a persistent index.
All 10 tools via mcporter
| Tool | Purpose |
|---|---|
aim_memory_store | Create new entities (components, people, concepts) |
aim_memory_link | Create typed relations between entities |
aim_memory_add_facts | Append observations to existing entities |
aim_memory_forget | Delete entities (cascades to their relations) |
aim_memory_remove_facts | Delete specific observations from an entity |
aim_memory_unlink | Delete specific relations |
aim_memory_read_all | Dump entire knowledge graph for a context |
aim_memory_search | Substring search across names, types, observations |
aim_memory_get | Exact lookup by entity name(s) |
aim_memory_list_stores | List all databases (project-local + global) |
Choosing where to store: project vs global
| Use case | location | context | Resulting file | Shareable? |
|---|---|---|---|---|
| Team/project knowledge | "project" | omit | .aim/memory.jsonl | ✓ commit it |
| Personal notes on a project | "global" | omit | ~/.aim/memory.jsonl | ✗ stays local |
| Personal named database | "global" | "work" | ~/.aim/memory-work.jsonl | ✗ stays local |
Default: omit context:, use location: "project" — produces .aim/memory.jsonl in the project root. Commit this file to share architectural knowledge with the team. The global context-loader hook also reads this file automatically on session start.
Only use context: when you need multiple separate graphs in the same project (rare). Named contexts create memory-{name}.jsonl files which are harder to discover and don't share well.
Example: build a project knowledge graph
# Initialize once
mkdir .aim ← creates project-local storage
# Store entities — no context: needed
mcporter call knowledge-graph.aim_memory_store(
location: "project",
entities: [
{"name": "AuthService", "entityType": "service", "observations": ["Handles JWT auth", "Stateless"]},
{"name": "UserRepository", "entityType": "repository", "observations": ["PostgreSQL", "Owns user table"]}
]
)
# Link them
mcporter call knowledge-graph.aim_memory_link(
location: "project",
relations: [
{"from": "AuthService", "to": "UserRepository", "relationType": "depends_on"}
]
)
# Query later
mcporter call knowledge-graph.aim_memory_search(query: "auth")
mcporter call knowledge-graph.aim_memory_get(names: ["AuthService"])
Personal notes (not committed)
mcporter call knowledge-graph.aim_memory_store(
location: "global",
entities: [{"name": "my-note", "entityType": "note", "observations": ["Personal observation"]}]
)
Storage mechanics (important for correct usage)
- Project-local file:
.aim/memory.jsonl— created whenlocation: "project"and nocontext:given - Global file:
~/.aim/memory.jsonl— created whenlocation: "global" - Auto-detection: if
.aim/exists in project root, project-local is used automatically whenlocationis omitted - Full rewrite: every write operation rewrites the entire file — keep graphs focused, not massive
- No concurrency: do not run two sessions writing to the same graph simultaneously
- Safety marker: every file starts with
{"type":"_aim","source":"mcp-knowledge-graph"}— do not edit files manually unless you preserve this
Entity and relation design
Entity: {name, entityType, observations[]}
- name: unique identifier (e.g. "AuthService", "UserController")
- entityType: semantic category (service, repository, module, concept, decision, person)
- observations: string[] of facts — append via aim_memory_add_facts
Relation: {from, to, relationType}
- relationType: active-voice verb (depends_on, calls, owns, extends, implements, manages)
- directional: from→to and to→from are different
Naming conventions:
- Entity names:
PascalCasefor code components,snake_casefor concepts - Relation types:
snake_caseverbs
Search behavior (know the limits)
aim_memory_search— substring match, case-insensitive, across name + type + observationsaim_memory_get— exact name match only, case-sensitive- No semantic/vector search — if you stored "AuthService handles JWT", searching "authentication" will NOT find it; "JWT" will
- Implication: use consistent, predictable observation wording when storing facts
Initializing a project graph
mkdir .aim
Commit .aim/memory.jsonl to share the graph with the team — it's just a JSONL file, safe to version-control.
If you want personal notes excluded from commits, add ~/.aim/ to nothing (it's already outside the repo). Only add .aim/*.jsonl to .gitignore if the graph contains secrets or machine-specific paths that shouldn't be shared.
Limitations
- Large graphs degrade performance (full in-memory load per operation)
- No append mode — each write rewrites the whole file
- No fuzzy or semantic search — keyword precision matters
- No versioning or rollback built-in
- Project detection searches up 5 directory levels for
.git,package.json,.aim, etc.