Skip to main content

lean-ix — SAP LeanIX GraphQL Proxy

⚠️ DEPRECATED — this package has been merged into dvm-eahelper (pip install dvm-eahelper), which combines the proxy, download and graph loading in one CLI and adds KuzuDB support. Use eahelper proxy / eahelper download instead. This repo is archived and receives no further updates.

A local proxy server that:

  • Connects to your already-logged-in browser via Playwright CDP
  • Extracts the active Bearer token from LeanIX network requests
  • Exposes a local GraphQL endpoint that proxies to LeanIX
  • Serves a GraphiQL UI for interactive exploration

Prerequisites

  • Python 3.14+ and uv
  • Google Chrome or Microsoft Edge installed
  • Playwright browsers installed (one-time step)
# One-time: install Playwright browser binaries
uv run playwright install chromium

Quick Start

Step 1 — Launch a debug Edge/Chrome instance

If Edge or Chrome is already running, you cannot simply add --remote-debugging-port to a new shortcut — the flag is silently ignored and the port never opens. You must launch a separate isolated instance using a different --user-data-dir.

# Edge (recommended — already installed on Windows)
Start-Process "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" `
  "--remote-debugging-port=9222 --user-data-dir=C:\Temp\edge-debug --no-first-run --no-default-browser-check"

# Chrome
Start-Process "C:\Program Files\Google\Chrome\Application\chrome.exe" `
  "--remote-debugging-port=9222 --user-data-dir=C:\Temp\chrome-debug --no-first-run"

Verify the debug port is active before continuing:

Invoke-RestMethod http://localhost:9222/json/version

You should see a JSON response with browser version info. If you get a connection error, the browser did not start with the debug port — check that you closed all existing windows of that browser first, or that the --user-data-dir path differs from your normal profile.

Log in to LeanIX in that browser window before proceeding.

Step 2 — Start the proxy

cd lean-ix
dvm-leanix

You will be prompted for the LeanIX workspace URL if not provided via --url.
The tool connects to Chrome, captures the Bearer token, then starts the local server.

Step 3 — Open GraphiQL

Navigate to: http://localhost:8765/graphql


CLI Options

dvm-leanix [OPTIONS]

Options:
  --url URL           LeanIX workspace base URL
                      (default: https://eu-10.leanix.net/YourInstance)
  --port PORT         Local port (default: 8765)
  --connect CDP_URL   Chrome DevTools Protocol endpoint (default: http://localhost:9222)
  --token TOKEN       Use this Bearer token directly — skips browser extraction
  --api-token KEY     LeanIX Technical User API key — exchanges for Bearer token via OAuth2
                      (no browser needed; also read from env var LEANIX_API_TOKEN)
  --ca-bundle PATH    PEM CA bundle (corporate SSL proxy fix)
  --no-verify-ssl     Disable SSL verification entirely (insecure)

Examples

# Use default URL, prompted if missing
dvm-leanix

# Specify workspace URL explicitly
dvm-leanix --url https://eu-10.leanix.net/MyOtherWorkspace

# Use Technical User API key (no browser needed)
dvm-leanix --api-token "your-api-key-here"

# API key via environment variable
$env:LEANIX_API_TOKEN = "your-api-key-here"
dvm-leanix

# Corporate SSL proxy — point at exported CA bundle
dvm-leanix --ca-bundle "$env:USERPROFILE\.lean-ix\corporate-ca.pem"

# Disable SSL verification (quick test only)
dvm-leanix --no-verify-ssl

# Use a known Bearer token (no browser needed)
dvm-leanix --token "eyJhbGci..."

# Different port
dvm-leanix --port 9000

Endpoints

Method Path Description
GET / Redirects to /graphql
GET /graphql GraphiQL interactive UI
POST /graphql GraphQL proxy to LeanIX
GET /health Health check + upstream URL
GET /token Show masked current Bearer token
POST /token Replace Bearer token at runtime

Replace token at runtime

If the token expires, refresh it without restarting:

Invoke-RestMethod -Uri http://localhost:8765/token -Method POST `
  -ContentType "application/json" `
  -Body '{"token": "eyJhbGci..."}'


Technical User Credentials (No Browser Required)

For automated scripts, CI pipelines, or headless environments you can authenticate with a Technical User API key instead of a browser session.

Create a Technical User

  1. In your LeanIX workspace go to Administration → Technical Users
  2. Click Create Technical User, set a name, assign roles
  3. Copy the generated API key (shown only once)

Start the proxy with an API key

# Pass directly
dvm-leanix --api-token "your-api-key-here"

# Or export as environment variable
$env:LEANIX_API_TOKEN = "your-api-key-here"
dvm-leanix

The proxy exchanges the key for a Bearer token via OAuth2 at startup and automatically re-exchanges it whenever the token expires — no browser interaction needed.

How it works

API key
  │
  │  POST /services/mtm/v1/oauth2/token
  │  auth: ("apitoken", API_KEY)
  │  body: grant_type=client_credentials
  ▼
Bearer access_token
  │
  ▼
server.py (FastAPI on localhost:8765)
  │  POST /graphql  { query, variables }
  │  Authorization: Bearer <token>
  ▼
https://eu-10.leanix.net/services/pathfinder/v1/graphql

SAP LeanIX GraphQL API

Full reference: docs/graphql-api.md

The SAP LeanIX GraphQL API conforms to the October 2021 GraphQL specification.

Key concepts

Concept Detail
Fact Sheets Core entities: Application, ITComponent, BusinessCapability, Process, Interface, DataObject, Provider, TechnicalStack, UserGroup, Project
Queries Read data — factSheet(id), allFactSheets(filter, sort, first, after)
Mutations Write data — createFactSheet, updateFactSheet, archiveFactSheet
Pagination Relay cursor-based (first + after with pageInfo.endCursor)
Filtering facetFilters with OR / AND / NOR operators on facet keys

GraphQL endpoint

POST https://{HOST}/services/pathfinder/v1/graphql
Authorization: Bearer {access_token}
Content-Type: application/json

Quick example

{
  allFactSheets(factSheetType: Application, first: 10) {
    totalCount
    pageInfo { hasNextPage endCursor }
    edges {
      node { id name displayName lxState completion { percentage } }
    }
  }
}

Error handling

GraphQL always returns HTTP 200. Check the errors array in the response body:

{
  "data": null,
  "errors": [{ "message": "No fact sheet found with id '...'" }]
}

See docs/graphql-api.md for filtering, pagination, mutations, the REST migration guide, and best practices.


Architecture

Browser (logged in)
    │
    │  Chrome DevTools Protocol (port 9222)
    ▼
token.py  ── intercepts Authorization header ──► Bearer token
    │
    ▼
server.py (FastAPI on localhost:8765)
    │  POST /graphql  { query, variables }
    │
    │  Authorization: Bearer <token>
    ▼
https://eu-10.leanix.net/services/pathfinder/v1/graphql

Troubleshooting

"Could not connect to browser at http://localhost:9222"
→ If Edge/Chrome is already running, the --remote-debugging-port flag is silently ignored by any new window you open — it only works on a fresh browser process. Launch a separate isolated instance with its own profile:

Start-Process "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" `
  "--remote-debugging-port=9222 --user-data-dir=C:\Temp\edge-debug --no-first-run --no-default-browser-check"

Then verify the port is open before retrying lean-ix:

Invoke-RestMethod http://localhost:9222/json/version   # must return JSON

"Timed out waiting for a Bearer token"
→ No LeanIX API calls were detected. Make sure you are logged in and try navigating within LeanIX to trigger an API request.

SSL: CERTIFICATE_VERIFY_FAILED — self-signed certificate in chain
→ Your corporate network uses SSL inspection (a man-in-the-middle proxy that replaces certificates with ones signed by an internal CA). Python's SSL stack rejects these because the corporate root CA is not in its trust bundle.

Option 1 — Export the corporate CA and point lean-ix at it (recommended)

# Export all trusted root CAs from the Windows certificate store to a PEM file
$certs = Get-ChildItem -Path Cert:\LocalMachine\Root
$pem = $certs | ForEach-Object { "-----BEGIN CERTIFICATE-----`n" + [Convert]::ToBase64String($_.RawData, 'InsertLineBreaks') + "`n-----END CERTIFICATE-----" }
$pem | Set-Content -Path "$env:USERPROFILE\.lean-ix\corporate-ca.pem" -Encoding ascii

Then run lean-ix with the bundle:

dvm-leanix --ca-bundle "$env:USERPROFILE\.lean-ix\corporate-ca.pem"

Option 2 — Disable verification entirely (quick test only, not recommended)

dvm-leanix --no-verify-ssl

Token expired mid-session
→ Navigate in the LeanIX browser tab (which triggers a token refresh) then POST the new token to /token, or restart lean-ix.

Metadata

Release files for dvm-leanix 0.5.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dvm-leanix 0.5.3
File Size Uploaded
dvm_leanix-0.5.3.tar.gz 97.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for dvm-leanix 0.5.3
File Interpreter ABI Platform
dvm_leanix-0.5.3-py3-none-any.whl Python 3 none any Details

Total release size: 131.7 kB

Release files / dvm_leanix-0.5.3.tar.gz

Download URL dvm_leanix-0.5.3.tar.gz
Size 97.9 kB
Tags Source
SHA-256 checksum
How to use checksums
9fbdb73bf7f78dab0cd4778b2f69cc1cbbc8eb431bbae3643ed971a058ba9e8c
BLAKE2b-256 checksum
How to use checksums
53013d29c358683642eead707dbc6ecb587ab2660d6a20502b77342290d24b33
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 12, 2026.

Transparency log

Release files / dvm_leanix-0.5.3-py3-none-any.whl

Download URL dvm_leanix-0.5.3-py3-none-any.whl
Size 33.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
df742e3c69b3f240eca9f70984a243e200ecb58993593c80ba782b09ddad90ee
BLAKE2b-256 checksum
How to use checksums
0de5e7a98717e2304faa0f7ef0717e13a8c0564762ca365fff78a94c33d5daa5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 12, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.3 This release

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page