Metadata-Version: 2.4
Name: kglite-visual
Version: 0.1.9
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Rust
Classifier: Topic :: Scientific/Engineering :: Visualization
License-File: LICENSE
Summary: Interactive WebGL visualization for .kgl knowledge graphs
Keywords: graph,knowledge-graph,visualization,webgl,kglite
Author-email: Kristian dF Kollsgård <kkollsg@gmail.com>
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://github.com/kkollsga/kglite-visual/blob/main/CHANGELOG.md
Project-URL: Homepage, https://github.com/kkollsga/kglite-visual
Project-URL: Issues, https://github.com/kkollsga/kglite-visual/issues
Project-URL: Repository, https://github.com/kkollsga/kglite-visual

# kglite-visual: see a knowledge graph, and let an agent drive it

[![PyPI version](https://img.shields.io/pypi/v/kglite-visual)](https://pypi.org/project/kglite-visual/)
[![Python versions](https://img.shields.io/pypi/pyversions/kglite-visual)](https://pypi.org/project/kglite-visual/)
[![License: MIT](https://img.shields.io/pypi/l/kglite-visual)](https://github.com/kkollsga/kglite-visual/blob/main/LICENSE)
[![Docs](https://img.shields.io/readthedocs/kglite-visual)](https://kglite-visual.readthedocs.io)

<!-- The pyversions badge reads `requires-python` (>=3.10). The extension is
     abi3-py310, so one wheel per platform serves every CPython from 3.10 up
     and there are deliberately no per-version classifiers to keep in step.
     The Docs badge stays red until the project is imported on readthedocs.org
     under the slug `kglite-visual`; .readthedocs.yaml already carries the
     whole build config. -->

kglite-visual is an interactive viewer, a headless renderer and an agent
interface for `.kgl` knowledge-graph files produced by
[KGLite](https://github.com/kkollsga/kglite). One command opens a browser on a
localhost server; the same binary draws an image without one; and while the
server runs it speaks the Model Context Protocol, so **an agent can drive the
window you are looking at**.

The Python wheel has no required runtime dependencies: the graph engine, the
HTTP server and the WebGL frontend bundle are all inside one compiled
extension. No Node, no separate server process, no database service.

## Quick Start

The released package:

```bash
pip install kglite-visual==0.1.9
kglite-visual graph.kgl
```

Open the downloadable 17-node team sample from
[Getting started](https://kglite-visual.readthedocs.io/en/stable/getting-started.html). The
[first exploration](https://kglite-visual.readthedocs.io/en/stable/first-exploration.html)
takes it through browse, inspect, query, filter, calculate, save and export.

<p align="center">
  <img src="https://raw.githubusercontent.com/kkollsga/kglite-visual/8870e9643bb12c930475619fe0ffe6f3291ad40f/docs/_static/team-overview.png"
       alt="The kglite-visual workspace showing the team sample"
       width="720">
</p>

What you land on is a type-level meta-graph, rather than every instance in the
source. `.kgl` files reach 100M+ nodes, so you inspect counts first and load a
bounded slice only when it is useful.

Two more commands, no server and no browser in either:

```bash
kglite-visual render graph.kgl --meta -o schema.svg      # one image, one JSON line
kglite-visual export graph.kgl --format gexf -o out.gexf # one file for somebody else's tool
```

Then hand the running server to an agent. The MCP endpoint is on the same port,
and its URL is printed on the same stdout line as everything else:

```json
{"url":"http://127.0.0.1:54137/","port":54137,"pid":69850,"graph":"graph.kgl","mcp":"http://127.0.0.1:54137/mcp"}
```

**→ [Getting started](https://kglite-visual.readthedocs.io/en/latest/getting-started.html) ·
[Agents and MCP](https://kglite-visual.readthedocs.io/en/latest/agents.html).**

## What makes it different

Three things this does that a graph viewer normally does not.

**An agent drives the window you are watching.** The running server speaks MCP
at `/mcp` — no second process to start, no discovery file, nothing to install:
attaching an agent is pointing it at a URL. Twenty-seven tools act on **one shared
view**, with ordered changes and optional revision checks: read what is on screen, put a Cypher result into it,
expand or collapse, highlight, zoom, recolour, re-lay-out, export it, draw a
picture of it, and run the queries *you* saved under the names you chose.
Whoever changes the view — you, the agent, a `curl` — every connected window
sees the change immediately. Watching an agent expand a type and zoom to what
it found is the feature, not a side effect of it.
**→ [Agents and MCP](https://kglite-visual.readthedocs.io/en/latest/agents.html).**

**The honesty model: truncation is drawn into the picture.** A graph viewer is
a machine for showing you less than there is, and the design position here is
that the subset must name itself. The response bound lives in **core**, not in
the UI — a guarantee the client implements is not a guarantee — so a `curl`, an
agent and a second tab all hit the same ceiling. Every bounded answer carries
`{returned, total, truncated}`; a slice carries *two* of those, because nodes
and links share one byte budget and a complete node list can sit beside an
incomplete link list. And because an image travels without its response, the
banner is drawn **into** the image, beside three more counts for the other ways
a picture can be less than its input: `types_shown` (a canvas too small for the
schema draws the largest types and says `top 24 of 98`), `names_shown` (labels
that lost their cell keep their circle and lose their name), and `folded` (a
fan too big to read is one wedge saying how big it is).
**→ [The honesty model](https://kglite-visual.readthedocs.io/en/latest/viewer/honesty.html).**

**Layouts chosen from the graph's own structure — including a real map.** A
force layout is the right tool for a graph with no discoverable shape and the
wrong one for a star, a bipartite result or a schema with disconnected
families, which is most of what a real graph hands it. So a neighbourhood is
drawn as hop rings, a community-structured graph as packed islands with a quiet
boundary round each, and unattached nodes as one labelled grid. And where the
nodes carry coordinates there is `--layout geo`: an equirectangular projection
whose longitudes are corrected by the cosine of the data's mid-latitude — so a
shelf at 68°N comes out its own shape rather than 2.7× too wide — over the
world's real coastline at **three scales chosen by how much of the world the
frame covers**, so a North Sea crop gets the fjords and a world map does not
carry 400,000 points nothing can resolve. Nodes with no coordinate go in a
labelled tray with a count, never dropped.
**→ [Layouts](https://kglite-visual.readthedocs.io/en/latest/viewer/layouts.html).**

## From Python, and from a notebook

```python
import kglite_visual as kv

view = kv.show("graph.kgl")     # the same server, in-process
view.url                        # 'http://127.0.0.1:54137/'
view.launch_info                # {'url', 'port', 'pid', 'graph', 'mcp'}
view.close()                    # stops it, frees the port

# Or hand over an in-memory kglite graph — through to_bytes(), never the disk.
import kglite
view = kv.show(kglite.load("graph.kgl"))
```

In a notebook the returned object renders itself in the cell: a proxy-prefixed
iframe where `jupyter-server-proxy` can reach the port, and **no iframe at
all** — the URL plus an `ssh -N -L` hint — where the kernel looks remote,
because a localhost iframe from a remote kernel is a silently blank frame.

`show(path)` is the large-graph answer: handing over an in-memory graph costs
about 2× the graph's size at the moment of the call.
**→ [Python API](https://kglite-visual.readthedocs.io/en/latest/python.html).**

## Render and export

The browser’s Export dialog previews visible instances and exact retained
relationships, the wider loaded-node induced graph, or a deterministic SVG/PNG.
Downloads refuse stale previews after shared changes. The image uses a server
layout, separate from the browser camera. Data tables also export scoped CSV.

```bash
# an image: --meta, --cypher "…" or --expand type=T rel=R dir=out
kglite-visual render graph.kgl --meta -o schema.svg
kglite-visual render graph.kgl --cypher "MATCH (f:Field) RETURN f" --layout geo --format png

# a file: graphml | gexf | csv | csv-edges | json
kglite-visual export graph.kgl --format gexf -o graph.gexf
kglite-visual export graph.kgl --format csv --cypher "MATCH (n:Field) RETURN n"
```

The render's layout is **seeded and deterministic** — the same request produces
the same bytes, forever — so `--seed` is how you get a *different* arrangement
of the same data, and an exact golden baseline is possible at all. Each command
writes its file and prints one JSON line describing it; nothing else ever
touches stdout.
**→ [Render](https://kglite-visual.readthedocs.io/en/latest/render.html) ·
[Export](https://kglite-visual.readthedocs.io/en/latest/export.html).**

## Requirements

CPython 3.10+ (one abi3 wheel serves every version from 3.10 up) on macOS,
Linux and Windows, plus a `.kgl` file supported by the embedded KGLite reader —
this version pins `kglite 0.17.3`, which reads compatible files written by
older releases. Building from source additionally needs a
Rust toolchain; the published wheels and the source distribution both carry a
prebuilt frontend, so neither needs Node at install time.

## Documentation

Full docs at **[kglite-visual.readthedocs.io](https://kglite-visual.readthedocs.io)**.

- **[Getting started](https://kglite-visual.readthedocs.io/en/stable/getting-started.html)** — install the package and open the sample.
- **[Your first exploration](https://kglite-visual.readthedocs.io/en/stable/first-exploration.html)** — browse, inspect, query, filter, calculate, save and export one graph.
- **[The viewer](https://kglite-visual.readthedocs.io/en/latest/viewer/index.html)** — the app in full:
  [the honesty model](https://kglite-visual.readthedocs.io/en/latest/viewer/honesty.html) ·
  [layouts](https://kglite-visual.readthedocs.io/en/latest/viewer/layouts.html) ·
  [query surfaces](https://kglite-visual.readthedocs.io/en/latest/viewer/queries.html) (editor, saved queries, generated tables, the path builder, `PROFILE`/`EXPLAIN`) ·
  [appearance and filtering](https://kglite-visual.readthedocs.io/en/latest/viewer/appearance.html).
- **[Agents and MCP](https://kglite-visual.readthedocs.io/en/latest/agents.html)** — the launch contract, the JSON twin, the twenty-seven tools, `window.__kglv`, and what an agent may claim about a screen it cannot see.
- **[Python API](https://kglite-visual.readthedocs.io/en/latest/python.html)** · **[CLI reference](https://kglite-visual.readthedocs.io/en/latest/cli.html)** · **[Render](https://kglite-visual.readthedocs.io/en/latest/render.html)** · **[Export](https://kglite-visual.readthedocs.io/en/latest/export.html)**.
- **[Concepts](https://kglite-visual.readthedocs.io/en/latest/concepts/index.html)** —
  [bounds in core](https://kglite-visual.readthedocs.io/en/latest/concepts/bounds-in-core.html) ·
  [the protocol](https://kglite-visual.readthedocs.io/en/latest/concepts/protocol.html) ·
  [storage](https://kglite-visual.readthedocs.io/en/latest/concepts/storage.html) ·
  [memory](https://kglite-visual.readthedocs.io/en/latest/concepts/memory.html).

Rendering is [cosmos.gl](https://cosmosgl.dev) (MIT, OpenJS Foundation): a
WebGL GPU force layout, fed over a binary protocol — typed-array buffers for
topology and positions, JSON for metadata.

## Stability

Alpha, pre-1.0. The launch contract (one JSON line: `url`, `port`, `pid`,
`graph`, `mcp`), the render and export summary lines, and the MCP tool **names**
are the surfaces to depend on; everything else may move.
[CHANGELOG.md](https://github.com/kkollsga/kglite-visual/blob/main/CHANGELOG.md)
records what a user can see change.

## License

MIT — see [LICENSE](https://github.com/kkollsga/kglite-visual/blob/main/LICENSE).

