Metadata-Version: 2.4
Name: panel-live-server
Version: 0.4.0
Summary: Panel Live Server is a local Panel web server that executes Python code snippets and renders the resulting visualizations as live, interactive web pages.
Project-URL: Homepage, https://github.com/panel-extensions/panel-live-server
Project-URL: Source, https://github.com/panel-extensions/panel-live-server
Author-email: MarcSkovMadsen <marc.skov.madsen@gmail.com>
Maintainer-email: MarcSkovMadsen <marc.skov.madsen@gmail.com>
License: BSD
License-File: LICENSE.txt
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: BSD License
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.12
Requires-Dist: fastmcp>=3.0
Requires-Dist: holoviews>=1.19
Requires-Dist: hvplot>=0.10
Requires-Dist: jinja2
Requires-Dist: packaging
Requires-Dist: panel-material-ui
Requires-Dist: panel>=1.5.0
Requires-Dist: playwright
Requires-Dist: psutil
Requires-Dist: pydantic>=2.0
Requires-Dist: requests
Requires-Dist: ruff
Requires-Dist: typer
Provides-Extra: dev
Requires-Dist: mkdocstrings[python]; extra == 'dev'
Requires-Dist: pre-commit; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: pytest-asyncio; extra == 'dev'
Requires-Dist: pytest-rerunfailures; extra == 'dev'
Requires-Dist: pytest-xdist; extra == 'dev'
Requires-Dist: typer; extra == 'dev'
Requires-Dist: watchfiles; extra == 'dev'
Requires-Dist: zensical; extra == 'dev'
Provides-Extra: mypy
Requires-Dist: mypy; extra == 'mypy'
Requires-Dist: panel>=1.5.0; extra == 'mypy'
Requires-Dist: types-requests; extra == 'mypy'
Requires-Dist: typing-extensions; extra == 'mypy'
Provides-Extra: pydata
Requires-Dist: altair; extra == 'pydata'
Requires-Dist: datashader; extra == 'pydata'
Requires-Dist: duckdb; extra == 'pydata'
Requires-Dist: geoviews; extra == 'pydata'
Requires-Dist: great-tables; extra == 'pydata'
Requires-Dist: holoviews; extra == 'pydata'
Requires-Dist: hvplot; extra == 'pydata'
Requires-Dist: hvsampledata; extra == 'pydata'
Requires-Dist: ipywidgets-bokeh; extra == 'pydata'
Requires-Dist: matplotlib; extra == 'pydata'
Requires-Dist: panel-full-calendar; extra == 'pydata'
Requires-Dist: panel-graphic-walker; extra == 'pydata'
Requires-Dist: panel-neuroglancer; extra == 'pydata'
Requires-Dist: panel-precision-slider; extra == 'pydata'
Requires-Dist: panel-splitjs; extra == 'pydata'
Requires-Dist: panel-web-llm; extra == 'pydata'
Requires-Dist: plotly; extra == 'pydata'
Requires-Dist: plotnine; extra == 'pydata'
Requires-Dist: polars; extra == 'pydata'
Requires-Dist: pooch; extra == 'pydata'
Requires-Dist: pyarrow; extra == 'pydata'
Requires-Dist: pydeck; extra == 'pydata'
Requires-Dist: scikit-image; extra == 'pydata'
Requires-Dist: scikit-learn; extra == 'pydata'
Requires-Dist: seaborn; extra == 'pydata'
Requires-Dist: setuptools; extra == 'pydata'
Requires-Dist: shapely; extra == 'pydata'
Requires-Dist: vega-datasets; extra == 'pydata'
Requires-Dist: yfinance; extra == 'pydata'
Description-Content-Type: text/markdown

# ✨ panel-live-server

[![CI](https://img.shields.io/github/actions/workflow/status/panel-extensions/panel-live-server/ci.yml?style=flat-square&branch=main)](https://github.com/panel-extensions/panel-live-server/actions/workflows/ci.yml)
[![conda-forge](https://img.shields.io/conda/vn/conda-forge/panel-live-server?logoColor=white&logo=conda-forge&style=flat-square)](https://prefix.dev/channels/conda-forge/packages/panel-live-server)
[![pypi-version](https://img.shields.io/pypi/v/panel-live-server.svg?logo=pypi&logoColor=white&style=flat-square)](https://pypi.org/project/panel-live-server)
[![python-version](https://img.shields.io/pypi/pyversions/panel-live-server?logoColor=white&logo=python&style=flat-square)](https://pypi.org/project/panel-live-server)

Panel Live Server is a local Panel web server and MCP server that executes Python code snippets
and renders the resulting visualizations as live, interactive web pages — enabling humans and AI
assistants to display and inspect Python outputs in real time.

![panel-live-server showcase](https://raw.githubusercontent.com/panel-extensions/panel-live-server/main/docs/assets/gif/panel-live-server-showcase.gif)

![panel-live-server MCP showcase](https://raw.githubusercontent.com/panel-extensions/panel-live-server/main/docs/assets/gif/panel-live-server-showcase-mcp.gif)

## Features

- **Two interfaces** — `pls serve` (standalone browser UI) and `pls mcp` (MCP server for AI assistants)
- **Any visualization library** — hvplot · plotly · altair · matplotlib · seaborn · holoviews · bokeh · and more
- **Validate before render** — `show` runs syntax, security, package, and extension checks before any rendering happens
- **Visual validation** — `screenshot` MCP tool lets the AI inspect the rendered output visually before presenting it, and returns the snippet's stdout plus any browser console errors alongside the image
- **Read a value, skip the picture** — `evaluate` MCP tool runs code in the server environment and returns its text output, so the AI can check a fact without launching a browser
- **Persistent storage** — SQLite database with full-text search; every snippet gets its own permanent URL
- **Auto-restart** — Panel subprocess is health-monitored and automatically restarted on failure
- **Works everywhere** — local, JupyterHub, GitHub Codespaces; URLs externalized automatically

## Installation

Install via uv, pip, or pixi — see the [Installation guide](https://panel-extensions.github.io/panel-live-server/tutorials/installation/) for full instructions including how to find your `pls` path.

```bash
uv tool install "panel-live-server[pydata]"
```

> **Pin your version** — this project is in its early stages. Pin to a specific version to avoid
> unexpected changes: `uv tool install "panel-live-server[pydata]==0.1.0a1"`

## Connect to your AI assistant

Use the **absolute path** printed by `which pls` above — not just `pls`.
Full setup instructions for each client: [docs → Connect to your MCP client](https://panel-extensions.github.io/panel-live-server/tutorials/installation/#connect-to-your-mcp-client)

| Client | Config location |
|---|---|
| **VS Code** | `.vscode/mcp.json` |
| **Cursor** | `~/.cursor/mcp.json` |
| **Claude Desktop** | `claude_desktop_config.json` |
| **Claude Code** | `claude mcp add panel-live-server -- /path/to/pls mcp` |
| **claude.ai** | HTTP transport + tunnel — see [docs](https://panel-extensions.github.io/panel-live-server/tutorials/installation/#connect-to-your-mcp-client) |

## Usage

```
$ pls

 Usage: pls [OPTIONS] COMMAND [ARGS]...

 Panel Live Server - Execute and visualize Python code snippets.

╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────╮
│ --version  -V        Show version and exit.                                                          │
│ --help               Show this message and exit.                                                     │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ───────────────────────────────────────────────────────────────────────────────────────────╮
│ serve   Start the Panel Live Server directly.                                                        │
│ mcp     Start as an MCP server for AI assistants.                                                    │
│ status  Check whether the Panel server is running.                                                   │
│ list    List resources (packages, etc.).                                                             │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯
```

You can also use `panel-live-server` but `pls` is shorter and easier to remember.

## Security

**Panel Live Server executes arbitrary Python.** That is its purpose — `show`, `screenshot`,
and `evaluate` all run code you or an AI assistant supplied, in the Panel server process, with
the full privileges of the user who started it. It can read and write your files and reach the
network exactly as any script you ran yourself could.

The validation `show` performs — syntax, a blocked-import list, ruff's security rules, package
availability — is a **guardrail, not a sandbox**. It catches the plausible mistakes an assistant
makes and refuses obviously inappropriate imports. It is not a security boundary and cannot be
relied on as one.

So:

- Run `pls` only in an environment you would be willing to run arbitrary code in.
- Don't expose the server's port to an untrusted network. It has no authentication; anyone who
  can reach `/api/snippet` or `/api/evaluate` can execute code in that environment.
- Treat a shared or production machine as the wrong place for it.

## Development

See the [Contributing guide](https://panel-extensions.github.io/panel-live-server/tutorials/contributing/) for the full setup (fork, install, connect to MCP client, run tests).

## ❤️ Contributing

Contributions are welcome! Please follow these steps:

1. Fork the repository.
2. Create a new branch: `git checkout -b feature/YourFeature`.
3. Make your changes and commit them: `git commit -m 'Add some feature'`.
4. Push to the branch: `git push origin feature/YourFeature`.
5. Open a pull request.

Please ensure your code passes all tests and linting before submitting.
