Introducing Panel Live Server: An MCP Server for Instant Python Visualization Rendering
A Faster Path from Code to Visualization
Anyone who has built interactive data applications with Panel, hvPlot, or HoloViews knows the workflow: write code, spin up a server, open a browser, refresh, repeat. For quick experiments and exploratory work, that loop adds up. And if you are working inside an AI assistant, asking Claude or GitHub Copilot to help you build a chart, there has been no clean way to actually see the result without leaving your tool.
Panel Live Server removes that friction. When connected to an MCP-compatible AI assistant like Claude, VS Code, or Cursor via the Model Context Protocol (MCP), you can point it at a dataset file or a URL and ask for a visualization directly in the chat. The assistant generates the code, Panel Live Server executes it, and the result comes back as a live, interactive visualization rendered inline in the chat via iframe, without leaving your IDE. You can also use it standalone from the terminal, submitting code through a browser UI and getting a persistent URL back instantly.
What is Panel Live Server?
Panel Live Server (panel-live-server) is an open-source local web server built around Panel. You submit Python code, anything from a simple chart to a full Panel dashboard, and it renders the output as a persistent, interactive web page. Every snippet gets its own URL stored in a SQLite database, so your visualizations survive server restarts and can be revisited or shared.
It is designed for two distinct use cases:
1. MCP Server
Give Claude, GitHub Copilot, Cursor, or any MCP-compatible AI assistant the ability to render visualizations directly in your IDE. Once connected, the assistant gains access to four tools, intended to be used in order:
list_packages: lists the Python packages installed in the server environment. Called once at the start of a session so the AI knows exactly what libraries it can use before writing any code.validate: validates code before rendering. Runs five checks in sequence: syntax, security, package availability, Panel extension declarations, and a runtime execution test. Returns a structured error with recovery hints on failure, or caches the result on success soshowcan reuse it at zero cost.show: executes the code and renders it as a live, interactive visualization, returning a URL. The user gets a real interactive page, not a static image.screenshot: gives the AI vision into the rendered visualization. A chart can run without errors and still look wrong. With this vision capability, the AI receives an actual PNG of what the user sees in the browser, allowing it to spot clipped legends, misaligned labels, or inconsistent margins and make precise fixes without editing the code blind.
The image below shows the MCP server connected in a VS Code IDE, rendering a visualization directly in the chat:
Once hooked up with an MCP client such as Claude, GitHub Copilot, or Cursor, just ask:
“Please show a quick and beautiful Matplotlib trading dashboard”
“Please show a basic, interactive Panel app with a slider”
“Please show the most beautiful matplotlib plot”
The AI calls show to render it and the visualization appears immediately in your chat interface, no manual setup required.
2. Standalone Server
Start a local web server and create interactive visualizations through a browser UI or REST API. Every snippet gets its own permanent URL.
The video below shows the standalone server running locally, with code submitted through the browser UI and rendered as an interactive web page instantly:
To get the server started, run:
pls serveOpen http://localhost:5077/add and submit any Python visualization:
import pandas as pd
import hvplot.pandas
df = pd.DataFrame({'Product': ['A', 'B', 'C', 'D'], 'Sales': [120, 95, 180, 150]})
df.hvplot.bar(x='Product', y='Sales', title='Sales by Product')Browse your visualizations at /feed, manage them at /admin, and link directly to any individual chart at /view?id=....
Try it Out
What You’ll Need
- Python 3.12 or later
- A package manager: uv, pip (built into Python), or pixi
Install Panel Live Server using pip, uv, or pixi:
pip install "panel-live-server[pydata]"uv tool install "panel-live-server[pydata]"pixi add --pypi "panel-live-server[pydata]"Then launch it:
# Standalone browser mode
pls serve
# MCP mode for AI assistants
pls mcpConnect to your MCP Client
Add to .vscode/mcp.json (create if it doesn’t exist):
{
"servers": {
"panel-live-server": {
"type": "stdio",
"command": "/path/to/pls",
"args": ["mcp"]
}
}
}Replace "command": "/path/to/pls" with the path printed by which pls
Once connected, ask your AI: “Show me a scatter plot of this data using the show tool.”
Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"panel-live-server": {
"command": "/path/to/pls",
"args": ["mcp"]
}
}
}Replace "command": "/path/to/pls" with the path printed by which pls
Open Cursor Settings → MCP and verify the green dot. Use Agent mode in chat.
Add to claude_desktop_config.json:
{
"mcpServers": {
"panel-live-server": {
"command": "/path/to/pls",
"args": ["mcp"]
}
}
}Replace "command": "/path/to/pls" with the path printed by which pls
claude mcp add panel-live-server -- /path/to/pls mcpReplace /path/to/pls with the path printed by which pls
Once connected, ask your AI: “Show me a scatter plot of this data using the show tool.”
claude.ai requires HTTP transport and a public URL. You can use any tunneling service (ngrok, Cloudflare, localhost.run, etc.). This example uses Cloudflare.
Terminal 1 — start the MCP server:
/path/to/pls mcp --transport http --port 8001Replace /path/to/pls with the path printed by which pls
Terminal 2 — tunnel for the MCP server:
cloudflared tunnel --url http://localhost:8001Terminal 3 — tunnel for the Panel server:
cloudflared tunnel --url http://localhost:5077Stop Terminal 1, set the Panel tunnel URL, and restart:
export PANEL_LIVE_SERVER_EXTERNAL_URL=<url-from-terminal-3>
/path/to/pls mcp --transport http --port 8001Then go to claude.ai → Settings → Connectors → Add custom connector and enter <url-from-terminal-2>/mcp as the URL.
Once connected, ask your AI: “Show me a scatter plot of this data using the show tool.”
Architecture
Panel Live Server uses a two-process architecture:
- MCP Server (
pls mcp): hosts thelist_packages,validate,show, andscreenshotMCP tools, starts the Standalone Server as a subprocess, and manages its lifecycle. - Standalone Server (
pls serve): executes Python code and serves visualizations as web pages. Exposes a REST API and four browser-accessible pages. - Browser: displays visualizations and management interfaces.
The show Tool
The show MCP tool is the primary interface for AI assistants. When called:
- The AI sends Python code via the
showtool - The MCP server validates the code (syntax, imports, test execution)
- The MCP server POSTs the snippet to the Panel server’s
/api/snippetendpoint - The Panel server stores the snippet in SQLite and returns a URL
- The MCP server returns the URL to the AI assistant
- The user accesses the visualization via URL in the browser (or inline in the MCP App UI)
show(
code="df.hvplot.bar(x='Product', y='Sales')",
name="Sales Chart",
description="Bar chart of product sales",
method="inline",
zoom=75
)The tool accepts:
code(required): Python code to executename: human-readable titledescription: one-sentence explanationmethod: execution method:"inline"(default) or"server"zoom: initial zoom level: 25, 50, 75, or 100
The screenshot Tool
The screenshot tool lets the AI see how a visualization actually looks in the browser. When called:
- The AI passes the
snippet_idreturned byshow - A headless Chromium browser navigates to the snippet’s
/viewpage - It waits for the content to mount and for Bokeh to finish painting
- A PNG image is captured and returned to the AI (not the user)
screenshot(
snippet_id="abc123",
width=1200,
height=800,
full_page=False
)The tool accepts:
snippet_id(required): the ID of an already-rendered snippet fromshowwidth: browser viewport width in pixels (default 1200)height: browser viewport height in pixels (default 800)full_page: ifTrue, captures the full scrollable page instead of just the viewport
The screenshot goes to the AI, not the user. The user already has the live interactive visualization. This tool gives the model vision — if the margins look off or the layout is inconsistent, the AI can see that directly and fix it, rather than editing the code blind.
Why an Independent Panel Server?
Running visualizations in an independent subprocess provides several key benefits:
- Isolation: if visualization code crashes or hangs, it does not affect the MCP server or the AI assistant’s session. Errors are captured and returned as structured messages.
- Decoupling: the Panel server and MCP server are independent. You can restart, update, or reconfigure the Panel server without restarting the MCP session.
- State management: the Panel server maintains its own SQLite database. Visualizations persist across MCP sessions and are accessible even if the MCP server is stopped.
- Resource control: long-running visualizations or large datasets run in a separate process with their own memory space.
Snippets and Execution Methods
A snippet is a stored code sample with metadata. Each snippet has a unique ID and URL-friendly slug, Python code, name and description, a status of pending, success, or error, detected package imports and Panel extensions, execution method, and timestamps.
Inline method (default): executes code and captures the last expression, wrapping it with
pn.panel()for display:import pandas as pd df = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]}) df # This expression is displayedBest for data exploration, quick charts, and any Python object (DataFrames, plots, widgets).
Server method: executes code that explicitly calls
.servable()on Panel components:import panel as pn pn.extension() slider = pn.widgets.IntSlider(name='Value', start=0, end=100) pn.Column(slider, pn.bind(lambda x: f'{x}² = {x**2}', slider)).servable()Best for complex interactive applications and multi-component dashboards.
Code executes inside a types.ModuleType namespace registered in sys.modules, so Panel decorators like @pn.cache and @pn.depends work correctly, just as they do in Panel application files.
Code Validation
Before submitting code to the Panel server, the MCP server runs a validation chain:
- Syntax check:
ast.parse()to catch syntax errors early - Extension check: verifies required Panel extensions are available (plotly, vega, deckgl, etc.)
- Execution test: runs the code in a module namespace to catch runtime errors
If validation fails, a structured error message is returned with recovery suggestions, without creating a database entry.
Persistent Storage
Every snippet is saved to a local SQLite database with full-text search. Visualizations are not ephemeral; they have stable URLs and survive server restarts. This makes it practical for building up a personal library of reusable snippets over time.
Panel Live Server adapts to where you are working:
- Local machine: standard
localhost:5077setup - JupyterHub: automatic URL externalization
- GitHub Codespaces: remote URL exposed correctly
The same pls serve or pls mcp command works across all of these, no environment-specific configuration needed.
Browser Pages
| URL | Purpose |
|---|---|
/view?id=... |
Executes and renders a single snippet |
/feed |
Browse all saved visualizations |
/add |
Web form to create snippets manually |
/admin |
Management table: search, inspect, delete |
Get Started with Panel Live Server
If you are interested in faster visualization workflows or AI-assisted data exploration with real rendered outputs, Panel Live Server is ready to try.
- Documentation: https://panel-extensions.github.io/panel-live-server/ Installation guides, concepts, and examples to get started.
- Source code: https://github.com/panel-extensions/panel-live-server Open-source development, issue tracking, and contribution guidelines.
Panel Live Server is actively evolving. If you are experimenting with MCP integrations, interactive dashboards, or AI-assisted visualization workflows, we encourage you to try it and share your feedback on Discourse or Discord. We would love to hear how you are using it and what you would like to see next.
Thanks to Marc Skov Madsen for designing and building the initial version of panel-live-server.

