Turn unstructured text into a queryable, versioned knowledge graph.
One graph API over any graph database, in Python and TypeScript.
- Text in, graph out. Extract entities and relations with any LLM, or without one.
- Any graph database. Neo4j, Memgraph, FalkorDB, HydraDB, or embedded Kuzu, behind one API.
- History built in. Every change is versioned, newer facts can retire older ones, and you can read the graph as of any past time.
- No vector store. Retrieval walks the graph from keyword matches and returns the source passages.
- SDK, CLI, and MCP server over the same graph, in Python and TypeScript.
pip install selfgraph # Neo4j, Memgraph, and HydraDB
pip install "selfgraph[all]" # plus LLM extraction, Kuzu, FalkorDB, spaCy, tiktoken, and MCPEvery extra is listed in install. For TypeScript, see typescript/README.md.
No server and no LLM, with pip install "selfgraph[kuzu]":
import asyncio
from selfgraph import KuzuStore, SelfGraph
async def main() -> None:
async with SelfGraph(store=KuzuStore("graph.kuzu")) as graph:
await graph.insert.ontology(
{
"entities": [
{"id": "person:jane", "type": "Person", "name": "Jane Doe"},
{"id": "company:acme", "type": "Company", "name": "Acme"},
],
"relations": [
{"from_entity": "person:jane", "type": "WORKS_AT", "to_entity": "company:acme"},
],
}
)
result = await graph.retrieve("who works at Acme")
print(result.context)
asyncio.run(main())With an LLM and a server:
from selfgraph import LLMConfig, Neo4jStore, SelfGraph
async with SelfGraph(
store=Neo4jStore("bolt://localhost:7687", auth=("neo4j", "password")),
llm=LLMConfig(provider="anthropic", model="claude-sonnet-5-5"),
) as graph:
await graph.insert.text("Soham prefers HydraDB. The team picked it for temporal history.")
result = await graph.retrieve("which database and why")
print(result.context)SyncSelfGraph has the same API without await. Without an LLM, insert.text falls back to spaCy or a simple regex pass; see inserting.
from selfgraph import CypherStore, FalkorDBStore, HydraDBStore, KuzuStore, Neo4jStore
Neo4jStore("bolt://localhost:7687", auth=("neo4j", "password"))
CypherStore("bolt://localhost:7687", auth=("user", "password")) # Memgraph and other Bolt engines
FalkorDBStore(host="localhost", port=6379)
KuzuStore("graph.kuzu") # embedded
HydraDBStore("bolt://127.0.0.1:17687", auth=("neo4j", "<token>")) # HydraDB 0.4.0 or newerSee backends to configure from settings or add your own store.
export SELFGRAPH_AUTH=neo4j:password
selfgraph --store neo4j --uri bolt://localhost:7687 insert text "Jane runs Acme." --source-id notes
selfgraph --store neo4j --uri bolt://localhost:7687 retrieve "who runs Acme" --context-onlyselfgraph mcp serves the same API as MCP tools. Stdio clients do not pass your shell environment, so set the connection in env:
{
"mcpServers": {
"selfgraph": {
"command": "selfgraph",
"args": ["mcp"],
"env": {
"SELFGRAPH_STORE": "neo4j",
"SELFGRAPH_URI": "bolt://localhost:7687",
"SELFGRAPH_AUTH": "neo4j:password"
}
}
}
}- Install and quickstart
- Inserting: text, ontologies, LLM setup, custom prompts
- Schema: types, validation, contradictions, Neo4j interop
- Entity resolution: merging duplicates
- Resources: entities, relations, preferences, decisions, ids
- Retrieval and maintenance
- Backends, CLI, MCP, errors, TypeScript
Contributions start with an approved issue; see CONTRIBUTING.md. Join us on Discord.
Apache-2.0.
