Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

MagGraph

In-process Git-backed graph engine for AI semantic layers — powered by Rust

CI PyPI Python License

Why "MagGraph"? The name is short for Magpie — a Corvid. Corvids (ravens, crows, jays, and magpies) are renowned in animal cognition research for their remarkable intelligence, long-term memory, and sophisticated tool use. MagGraph is built to be the memory and knowledge layer for AI agents with those same qualities: a graph that thinks, remembers, and uses tools.

MagGraph stores knowledge as versioned Markdown nodes in your Git repository, with BFS/DFS traversal, Git-backed sync, external lakehouse content resolution, and a built-in MCP server scaffold — all from a zero-dependency pip install.


Install

pip install maggraph

Pre-built wheels are available for:

Platform Architectures
Linux (manylinux_2_28) x86_64 · aarch64
macOS Intel (x86_64) · Apple Silicon (arm64)
Windows x86_64

No Rust toolchain required — the Rust core is compiled into the wheel.


Quick start

import maggraph

# Load config + open the graph index
config = maggraph.load_config("maggraph.toml")
index  = config.open_index()

# List nodes
print(index.list_nodes())          # ['getting_started', 'welcome', ...]

# Read a node
node = index.read_node("welcome")
print(node.body)                   # full markdown body

# Search, backlinks, and recall
print(index.search("Welcome")[0]["id"])
print(index.backlinks("welcome"))
bundle = index.recall_bundle("welcome", reason="quick start")
print(bundle["markdown"])

# BFS traversal
result = index.traverse("welcome", depth=2, order="bfs")
print(result.to_markdown(index))   # formatted traversal report

# CRUD and memory helpers
index.create_memory_node("prefers_cli", "preference", "User prefers CLI-first UX.")
index.create_node("new_note", node_type="note", body="# Hi\n", links=["welcome"])
index.update_node("new_note", "# Updated\n")
index.suppress_node("new_note", reason="example")
index.unsuppress_node("new_note")
index.delete_node("new_note")

Async support

import asyncio, maggraph

async def main():
    index = maggraph.open_index("examples/basic/knowledge_graph")
    node  = await index.read_node_async("welcome")
    result = await index.traverse_async("welcome", depth=3, order="dfs")
    print(result.to_markdown(index))

asyncio.run(main())

Blocking Rust work runs on a Tokio thread pool — Python's event loop stays responsive.


Lakehouse content resolution

Resolve external data sources (S3, file://, HTTP) referenced from node frontmatter:

import maggraph

config = maggraph.load_config("maggraph.toml")  # mode = "lakehouse"
index  = config.open_index()
reader = config.open_lakehouse_reader()

# Resolve a node's external source (e.g. s3://bucket/data.parquet)
result = reader.read_node(index, "customer_churn_q2")
print(result.content.kind)          # "external_asset"
print(result.content.uri)           # "s3://corp-data/lake/churn.parquet"
print(result.content.format)        # "parquet"
print(result.content.to_markdown()) # agent-friendly summary

# Cache stats
print(reader.cache_len())    # 1
print(reader.cache_bytes())  # ~128

# Also callable directly on the index
result2 = index.read_node_with_content(reader, "customer_churn_q2")

maggraph.toml for lakehouse mode:

[storage]
mode = "lakehouse"
root_path = "./knowledge_graph"

[lakehouse]
remote_sources = [
  { uri = "s3://corp-data/lake", format = "parquet" }
]

MCP server scaffold

maggraph scaffold --mcp --output ./mcp_server

Generates a ready-to-run FastMCP server at ./mcp_server/server.py wired to your graph index — expose list_nodes, read_node, traverse, create_node, and delete_node as MCP tools with one command.


Git-backed sync

# Leader pushes a snapshot
maggraph sync push --message "Add Q2 analysis nodes"

# Follower (read-only) pulls
maggraph sync pull

API reference

Class / Function Description
load_config(path) Load maggraph.tomlResolvedConfig
open_index(root_path) Open graph index directly → GraphIndex
ResolvedConfig.open_index() Open index from config
ResolvedConfig.open_lakehouse_reader() Create a LakehouseReader
GraphIndex.list_nodes() All node ids (sorted)
GraphIndex.read_node(id) Node with metadata + body
GraphIndex.search(...) Structured search over ids, types, tags, frontmatter, links, body, and recency
GraphIndex.hybrid_search(...) Explainable lexical + graph + recency + optional semantic retrieval with temporal/project filters
GraphIndex.backlinks(id) Node ids that link to id
GraphIndex.changed_since(unix) Files modified after a Unix timestamp
GraphIndex.update_file(path) Refresh one changed markdown file in the index
GraphIndex.recall_bundle(id, ...) Compact agent retrieval dict with Markdown
GraphIndex.read_node_async(id) Async version
GraphIndex.traverse(id, depth, order) BFS/DFS → TraversalResult
GraphIndex.traverse_async(...) Async version
GraphIndex.create_node(...) Write new node to disk + index
GraphIndex.create_memory_node(...) Create typed memory nodes (preference, project_fact, decision, task, session_summary, bookmark, tool_failure)
GraphIndex.apply_memory_batch(...) Preview or apply reviewed update/suppress/unsuppress/merge operations as one rollback-capable batch
GraphIndex.update_node(id, body) Update body on disk
GraphIndex.delete_node(id) Delete node from disk + index
GraphIndex.suppress_node(id) / unsuppress_node(id) Mark/unmark stale or duplicate nodes
GraphIndex.merge_nodes(target, source) Merge duplicate source into canonical target
GraphIndex.read_node_with_content(reader, id) Resolve external content
LakehouseReader.read_node(index, id) NodeWithContent
LakehouseReader.read_node_async(index, id) Async version
LakehouseReader.cache_len() Entries in content cache
LakehouseReader.cache_bytes() Bytes in content cache
Node.id / .node_type / .body / .links / .source Node properties
Node.to_markdown() Full node as Markdown string
Node.to_dict() Node as plain Python dict
ResolvedContent.kind "local" / "text" / "external_asset"
ResolvedContent.body / .uri / .format Content details
ResolvedContent.to_markdown() Agent-friendly summary
NodeWithContent.node / .content Node + resolved content

Links


License

MIT OR Apache-2.0