pywry-orientation
When to reach for PyWry MCP tools (native webview rendering, Plotly, TradingView, AgGrid, chat) instead of writing…
This skill covers building PyWry widgets for Jupyter notebooks via MCP tools.
Claude Code
$ npx -y skills add deeleeramone/PyWry --skill jupyter --agent claude-code
Codex
$ npx skills add deeleeramone/PyWry --skill jupyter -a codex -y
Cursor
$ npx skills add deeleeramone/PyWry --skill jupyter -a cursor -y
Gemini CLI
$ npx skills add deeleeramone/PyWry --skill jupyter -a gemini-cli -y
GitHub Copilot
$ npx skills add deeleeramone/PyWry --skill jupyter -a github-copilot -y
OpenCode
$ npx skills add deeleeramone/PyWry --skill jupyter -a opencode -y
Windsurf
$ npx skills add deeleeramone/PyWry --skill jupyter -a windsurf -y
This skill covers building PyWry widgets for Jupyter notebooks via MCP tools.
There are **two approaches** for displaying widgets in Jupyter:
| Approach | Best For | Requires | |----------|----------|----------| | **AnyWidget** (recommended) | Native Jupyter integration, bidirectional comms | `pip install 'pywry[notebook]'` | | **IFrame** (fallback) | When anywidget unavailable | MCP server in headless mode |
---
AnyWidget provides native Jupyter widget integration with traitlet-based bidirectional communication. No iframe, no server - just native Jupyter widgets.
┌─────────────────────────────────────────────────────────┐
│ Jupyter Notebook │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Cell [1]: # Code from MCP agent │ │
│ │ from pywry.widget import PyWryWidget │ │
│ │ widget = PyWryWidget( │ │
│ │ content="<div>...</div>", │ │
│ │ height="400px" │ │
│ │ ) │ │
│ │ widget # Display in cell │ │
│ ├───────────────────────────────────────────────────┤ │
│ │ Output: ┌─────────────────────────────────────┐ │ │
│ │ │ [Native Jupyter Widget] │ │ │
│ │ │ Buttons, Charts, Tables, etc. │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
▲
│ Traitlet sync (bidirectional)
▼
┌─────────────────────────────────────────────────────────┐
│ Python Kernel │
│ PyWryWidget instance with .on() event handlers │
└─────────────────────────────────────────────────────────┘When asked to create an interactive widget in Jupyter with anywidget installed:
1. **Use `build_div` to build HTML content** 2. **Provide Python code for the user to run**
The MCP agent **cannot** directly instantiate Python objects in the user's kernel. Instead, provide code the user can execute.
When user asks: "Create a widget to tune learning rate and model type"
**Step 1**: Build the HTML content using MCP tools:
{
"tool": "build_div",
"arguments": {
"component_id": "output",
"content": "Adjust parameters below",
"style": "padding: 1rem; min-height: 100px;"
}
}**Step 2**: Provide this Python code to the user:
from pywry.widget import PyWryWidget
from pywry.toolbar import Toolbar, Slider, Select, Option, Button
# Build toolbar
toolbar = Toolbar(position="inside", items=[
Slider(label="Learning Rate", event="lr", min=0.001, max=0.1, step=0.001, value=0.01),
Select(label="Model", event="model", options=[
Option(label="Linear", value="linear"),
Option(label="Random Forest", value="rf")
]),
Button(label="Train", event="train", variant="primary")
])
# Build HTML with toolbar
html = f'''
<div id="output" style="padding: 1rem; min-height: 100px;">
Adjust parameters and click Train
</div>
{toolbar.render()}
'''
# Create and display widget
widget = PyWryWidget(content=html, height="350px")
# Handle events
def on_train(data, event_type, label):
print(f"Training with: {data}")
widget.emit("pywry:set-content", {"id": "output", "html": "<p>Training...</p>"})
widget.on("train", on_train)
widget # Display in cell| Class | Use Case | |-------|----------| | `PyWryWidget` | General HTML/toolbar widgets | | `PyWryPlotlyWidget` | Charts with Plotly.js bundled | | `PyWryAgGridWidget` | Data tables with AG Grid bundled |
from pywry.widget import PyWryPlotlyWidget
widget = PyWryPlotlyWidget(
figure={"data": [{"x": [1,2,3], "y": [4,5,6], "type": "scatter"}]},
height="450px"
)
# Handle plot click events
widget.on("plotly_click", lambda data, *_: print(f"Clicked: {data}"))
widgetfrom pywry.widget import PyWryAgGridWidget
import pandas as pd
df = pd.DataFrame({"A": [1, 2, 3], "B": ["x", "y", "z"]})
widget = PyWryAgGridWidget(
data=df.to_dict("records"),
columns=[{"field": "A"}, {"field": "B"}],
height="400px"
)
# Handle row selection
widget.on("row_selected", lambda data, *_: print(f"Selected: {data}"))
widget---
When anywidget is not installed, use the MCP server in headless mode to serve widgets via HTTP.
┌─────────────────────────────────────────────────────────┐
│ Jupyter Notebook │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Cell [1]: from IPython.display import IFrame │ │
│ │ IFrame("http://localhost:8765/widget/ │ │
│ │ abc123", width="100%", │ │
│ │ height=400) │ │
│ ├───────────────────────────────────────────────────┤ │
│ │ Output: ┌─────────────────────────────────────┐ │ │
│ │ │ [Your Widget Rendered Here] │ │ │
│ │ │ Buttons, Charts, Tables, etc. │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
▲
│ HTTP (iframe src)
▼
┌─────────────────────────────────────────────────────────┐
│ PyWry Widget Server (localhost:8765) │
│ Serves widget HTML at /widget/{widget_id} │
└─────────────────────────────────────────────────────────┘PyWry is a cross-platform app factory, rendering engine and UI toolkit for Python that produces native desktop, web, and notebook experiences from a single API.
When to reach for PyWry MCP tools (native webview rendering, Plotly, TradingView, AgGrid, chat) instead of writing…
Add OAuth2 authentication to PyWry apps — Google, GitHub, Microsoft, or any OIDC provider.
Autonomous PyWry application building using LLM sampling, elicitation, and progress reporting.
How an agent operates inside a PyWry chat widget — reading user messages, attachments, @-context, tool-call result cards,…
**STOP. THIS IS THE AUTHORITATIVE REFERENCE FOR ALL COMPONENTS.** **YOU MUST USE THE EXACT EVENT SIGNATURES DOCUMENTED HERE.**…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.