Download LeanIX factsheets and relationships and load them into Neo4j
Project description
dvm-eagraph — LeanIX → Neo4j Loader
Downloads Application, BusinessCapability, Interface and Organization factsheets (plus all relationships between them) from SAP LeanIX and loads them into Neo4j.
Installation
pip install dvm-eagraph
Or run without installing using uvx:
uvx dvm-eagraph -- --help
Note:
dvm-eagraphdepends ondvm-leanix. Ensure it is installed and available in your Python environment before use.
Prerequisites
| Requirement | Details |
|---|---|
| Neo4j running | Start the database in Neo4j Desktop before running the loader |
.env file |
Must contain NEO4J_URI, NEO4J_USERNAME, NEO4J_PASSWORD |
dvm-leanix proxy |
Must be running in a separate terminal before the loader is launched |
uv (optional) |
Required for uvx — install from docs.astral.sh/uv |
GitHub Copilot MCP Integration (Neo4j)
This project is pre-configured so that GitHub Copilot in VS Code can query the Neo4j database directly using natural language, via the mcp-neo4j-cypher MCP server.
How it works
The MCP server is configured in .vscode/settings.json. When Neo4j is running, Copilot can execute Cypher queries through three tools:
read_neo4j_cypher— run read queries (MATCH, RETURN)write_neo4j_cypher— run write queries (MERGE, CREATE, DELETE)get_neo4j_schema— introspect node labels and relationship types (requires APOC)
Setup
-
Install
uv— the MCP server is launched viauvx(no separate install needed after this):# Windows (PowerShell) powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# macOS / Linux curl -LsSf https://astral.sh/uv/install.sh | sh
-
Start Neo4j in Neo4j Desktop before using Copilot chat.
-
Open the project in VS Code — the
.vscode/settings.jsonis already configured:{ "github.copilot.chat.mcp.servers": { "neo4j": { "type": "stdio", "command": "uvx", "args": [ "mcp-neo4j-cypher", "--db-url", "bolt://localhost:7687", "--username", "neo4j", "--password", "password" ] } } }
Update the
--passwordvalue if your Neo4j password differs frompassword. -
Verify — in Copilot Chat, the Neo4j tools will appear in the MCP tools list. Ask a question like:
"How many Application nodes are in the graph?"
Changing credentials
If your Neo4j password is different, update .vscode/settings.json directly — or better, ask Copilot to query using your credentials. Do not commit passwords to source control; consider using a VS Code user settings override for the password.
Start the dvm-leanix proxy
dvm-leanix serve # uses default workspace URL + legacy SSL
The proxy authenticates via your browser and listens on http://localhost:8765/graphql.
Quick Start
# Full run: download from LeanIX, load into Neo4j
dvm-eagraph
# Or with uvx (no install needed):
uvx dvm-eagraph
Usage
dvm-eagraph [OPTIONS]
Options:
--proxy URL dvm-leanix GraphQL proxy URL
(default: http://localhost:8765/graphql)
--data-dir PATH Directory to save raw JSON files
(default: data/leanix)
--mapping PATH Path to metamodel mapping YAML
(default: metamodel-mapping.yaml in CWD, then bundled default)
--generate-mapping Scan LeanIX and write a mapping YAML, then exit
--all-factsheets Download every FactSheet type (ignores mapping filter)
--limit N Cap downloads to N records per FactSheet type and N rows per
relationship type (useful for testing)
--no-verify-ssl Disable SSL certificate verification (insecure)
--skip-download Load from previously saved JSON; skip LeanIX download
--skip-neo4j Download only; do not write to Neo4j
Common workflows
# Download only (inspect JSON before loading)
dvm-eagraph --skip-neo4j
# Quick end-to-end test with 10 records per type
dvm-eagraph --limit 10
# Load previously downloaded JSON into Neo4j (no LeanIX connection needed)
dvm-eagraph --skip-download
# Generate a mapping YAML from your live LeanIX workspace
dvm-eagraph --generate-mapping
# Use a custom mapping file
dvm-eagraph --mapping path/to/my-mapping.yaml
# Re-run against a different proxy
dvm-eagraph --proxy http://localhost:9000/graphql
# With uvx, passing arguments after --
uvx dvm-eagraph -- --skip-download --mapping my-mapping.yaml
Mapping File
The metamodel-mapping.yaml controls which LeanIX FactSheet types are downloaded and how they map to Neo4j labels and relationship types.
- Default: if no
metamodel-mapping.yamlexists in the working directory, the bundled default is used automatically. - Custom: place your own
metamodel-mapping.yamlin the working directory, or pass--mapping <path>. - Generate: run
dvm-eagraph --generate-mappingto scan the live workspace and produce a new file.
What Gets Downloaded
Factsheet types
| LeanIX Type | Neo4j Label | Key properties loaded |
|---|---|---|
Application |
:Application |
id, displayName, description, technicalSuitability, businessValue, lifecycle, … |
BusinessCapability |
:BusinessCapability |
id, displayName, description, level, … |
Interface |
:Interface |
id, displayName, description, dataFlowDirection, … |
Organization |
:Organization |
id, displayName, description, orgUnit, … |
All scalar fields returned by the LeanIX GraphQL schema are downloaded and stored as
node properties. The LeanIX id (UUID) is used as the unique identifier.
Raw JSON output
Downloaded data is saved to data/leanix/ for inspection and offline re-use:
data/leanix/
Application.json
BusinessCapability.json
Interface.json
Organization.json
Application_relations.json
BusinessCapability_relations.json
Interface_relations.json
Organization_relations.json
Graph Model
The script extends the base graph model with LeanIX data:
(Application)-[:SUPPORTS]->(BusinessCapability)
(Application)-[:EXPOSES]->(Interface)
(Interface)-[:CONSUMED_BY]->(Application)
(Interface)-[:CARRIES]->(DataObject)
(Application)-[:OWNED_BY]->(Organization)
(BusinessCapability)-[:CHILD_OF]->(BusinessCapability) # hierarchy
Relationship type mapping
LeanIX relation field names are mapped to Neo4j relationship types:
| LeanIX relation field | Neo4j relationship type |
|---|---|
relApplicationToBusinessCapability |
:SUPPORTS |
relApplicationToInterface |
:EXPOSES |
relInterfaceToApplication |
:CONSUMED_BY |
relInterfaceToDataObject |
:CARRIES |
relApplicationToDataObject |
:USES_DATA |
relToParent |
:CHILD_OF |
relApplicationToOrganization |
:OWNED_BY |
relOrganizationToApplication |
:OWNS |
relApplicationToITComponent |
:USES_COMPONENT |
relITComponentToApplication |
:USED_BY |
| (any other) | Auto-converted camelCase → UPPER_SNAKE_CASE |
Idempotency
The script is safe to re-run — it will update existing data, not duplicate it.
- Nodes: loaded with
MERGE (n:Label {id: row.id}) SET n += row
The LeanIX UUID is the stable key. Re-running updates all scalar properties. - Relationships: loaded with
MERGE (src)-[:TYPE]->(tgt)
Duplicate edges are never created. - Constraints:
CREATE CONSTRAINT IF NOT EXISTS— harmless to run repeatedly.
Architecture
dvm_eagraph.load_leanix
│
├── download_factsheets() ← lean_ix.download.fetch_all()
│ Introspects GraphQL schema, fetches all pages, writes {Type}.json
│
├── download_relations() ← lean_ix.download.fetch_all_relations()
│ Fetches all relation edges, deduplicates, writes {Type}_relations.json
│
├── load_saved_json() ← reads previously saved JSON (--skip-download)
│
└── load_to_neo4j()
├── create_constraints() UNIQUE on id per label
├── load_nodes() MERGE + SET per factsheet type
└── load_relationships() MERGE per relationship type (batched by type)
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Connection refused on proxy URL |
Proxy not running | Run dvm-leanix serve in another terminal |
AuthError from Neo4j |
Wrong credentials | Check .env values |
SSL / certificate errors |
Corporate proxy | Run dvm-leanix diagnose or use --no-verify-ssl |
| Empty download for a type | Type doesn't exist in workspace | Check available types with dvm-leanix download --list-types |
| Unknown relation in Neo4j | Unmapped LeanIX relation name | Add entry to metamodel-mapping.yaml |
List available types and relations
# List all factsheet types in the workspace
dvm-leanix download --list-types
# List all relation fields for a type
dvm-leanix download --type Application --list-relations
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dvm_eagraph-0.1.2.tar.gz.
File metadata
- Download URL: dvm_eagraph-0.1.2.tar.gz
- Upload date:
- Size: 78.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c942d4503dc2e8dac3f3e9053b02ae719184888f3cbaefcbefd2dd2a5472d46c
|
|
| MD5 |
bcac406238e31a7e1fc0224d9fb584b1
|
|
| BLAKE2b-256 |
83d6b82c7e40eae928f6b6ba875695034da9792514b1a0893ce73e7996c01f9b
|
Provenance
The following attestation bundles were made for dvm_eagraph-0.1.2.tar.gz:
Publisher:
publish.yml on divyavanmahajan/dvm-eagraph
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dvm_eagraph-0.1.2.tar.gz -
Subject digest:
c942d4503dc2e8dac3f3e9053b02ae719184888f3cbaefcbefd2dd2a5472d46c - Sigstore transparency entry: 1397726637
- Sigstore integration time:
-
Permalink:
divyavanmahajan/dvm-eagraph@f50cc636f32fe522f8f73852e42a0b0a56c42068 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/divyavanmahajan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f50cc636f32fe522f8f73852e42a0b0a56c42068 -
Trigger Event:
push
-
Statement type:
File details
Details for the file dvm_eagraph-0.1.2-py3-none-any.whl.
File metadata
- Download URL: dvm_eagraph-0.1.2-py3-none-any.whl
- Upload date:
- Size: 21.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c1184bd11725f648a5593128ff44846f2e6fa695a845de6a054f1d69fbca36c5
|
|
| MD5 |
d98ec30d6f3baa6c6f10506f7dca9593
|
|
| BLAKE2b-256 |
b6cc2add8536f1f4faddb04da83bdb501360836dd455c9a1193a84a14b05403a
|
Provenance
The following attestation bundles were made for dvm_eagraph-0.1.2-py3-none-any.whl:
Publisher:
publish.yml on divyavanmahajan/dvm-eagraph
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dvm_eagraph-0.1.2-py3-none-any.whl -
Subject digest:
c1184bd11725f648a5593128ff44846f2e6fa695a845de6a054f1d69fbca36c5 - Sigstore transparency entry: 1397726644
- Sigstore integration time:
-
Permalink:
divyavanmahajan/dvm-eagraph@f50cc636f32fe522f8f73852e42a0b0a56c42068 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/divyavanmahajan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f50cc636f32fe522f8f73852e42a0b0a56c42068 -
Trigger Event:
push
-
Statement type: