deeleeramone/pywry/jupyter

Claude Code and agent skill by deeleeramone/pywry

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Install

npx vskill@latest install deeleeramone/pywry/jupyter

SKILL.md

Jupyter Notebook Skill

This skill covers building PyWry widgets for Jupyter notebooks via MCP tools.

There are two approaches for displaying widgets in Jupyter:

ApproachBest ForRequires
AnyWidget (recommended)Native Jupyter integration, bidirectional commspip install 'pywry[notebook]'
IFrame (fallback)When anywidget unavailableMCP server in headless mode

Approach 1: AnyWidget (Recommended)

AnyWidget provides native Jupyter widget integration with traitlet-based bidirectional communication. No iframe, no server - just native Jupyter widgets.

Architecture
┌─────────────────────────────────────────────────────────┐
│ 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 │
└─────────────────────────────────────────────────────────┘
MCP Workflow for AnyWidget

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.

Example: Parameter Tuning Widget

When user asks: "Create a widget to tune learning rate and model type"

Step 1: Build the HTML content using MCP tools:

json
{
"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:

python
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
AnyWidget Classes
ClassUse Case
PyWryWidgetGeneral HTML/toolbar widgets
PyWryPlotlyWidgetCharts with Plotly.js bundled
PyWryAgGridWidgetData tables with AG Grid bundled
PyWryPlotlyWidget Example
python
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}"))
widget
PyWryAgGridWidget Example
python
from 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

Approach 2: IFrame (Fallback)

When anywidget is not installed, use the MCP server in headless mode to serve widgets via HTTP.

Architecture
┌─────────────────────────────────────────────────────────┐
│ 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} │
└─────────────────────────────────────────────────────────┘
MCP Tool Workflow (IFrame Mode)
Step 1: Create the Widget

Use create_widget to build your widget:

json
{
"tool": "create_widget",
"arguments": {
"title": "Parameter Tuner",
"html": "<div id='output'>Adjust parameters below</div>",
"height": 350,
"toolbars": [{
"position": "inside",
"items": [
{"type": "slider", "label": "Learning Rate", "event": "lr", "min": 0.001, "max": 0.1, "step": 0.001, "value": 0.01},
{"type": "select", "label": "Model", "event": "model", "options": [
{"label": "Linear", "value": "linear"},
{"label": "Random Forest", "value": "rf"}
]}
]
}]
}
}
Step 2: Provide Display Code to User

The create_widget tool returns:

json
{
"widget_id": "abc123",
"path": "/widget/abc123",
"created": true
}

IMPORTANT: You must give the user Python code to display the widget. Include this in your response:

python
from IPython.display import IFrame
IFrame("http://localhost:8765/widget/abc123", width="100%", height=350)

Replace abc123 with the actual widget_id and 350 with the height you used.

Step 3: Poll for Events

Use get_events to check for user interactions:

json
{
"tool": "get_events",
"arguments": {
"widget_id": "abc123",
"clear": true
}
}

Events contain the user's selections:

json
{
"events": [
{"event_type": "lr", "data": {"value": 0.05}},
{"event_type": "model", "data": {"value": "rf"}}
]
}
Step 4: Update the Widget

Use set_content to update displayed results:

json
{
"tool": "set_content",
"arguments": {
"widget_id": "abc123",
"component_id": "output",
"html": "<p>Training with LR=0.05, Model=Random Forest...</p>"
}
}
Example Response (IFrame Mode)

When asked to create a widget in Jupyter without anywidget, your response should look like:


I've created a parameter tuning widget. Run this code in a cell to display it:

python
from IPython.display import IFrame
IFrame("http://localhost:8765/widget/abc123", width="100%", height=350)

Use the sliders and dropdowns to adjust parameters. Let me know when you've made your selections and I'll process them.



Best Practices (Both Approaches)

Use position: "inside" for Toolbars

Place toolbars inside the widget to maximize vertical space in notebook cells:

json
{
"toolbars": [{
"position": "inside",
"items": [...]
}]
}
Keep Heights Modest

Notebook cells have limited vertical space. Use heights between 300-500px:

json
{
"height": 400
}
Include Plotly for Charts

Set include_plotly: true when building data visualizations:

json
{
"tool": "create_widget",
"arguments": {
"html": "<div id='chart'></div>",
"include_plotly": true,
"height": 450
}
}

Then use show_plotly or inject chart data via events.

Include AG Grid for Tables

Set include_aggrid: true for data tables:

json
{
"tool": "create_widget",
"arguments": {
"html": "<div id='table'></div>",
"include_aggrid": true,
"height": 400
}
}

Data Science Patterns

Parameter Exploration Widget

Create widgets that let users tune model parameters:

json
{
"tool": "create_widget",
"arguments": {
"title": "Hyperparameter Tuning",
"html": "<div id='results'>Select parameters and click Train</div>",
"height": 400,
"toolbars": [{
"position": "inside",
"items": [
{"type": "number", "label": "Epochs", "event": "epochs", "value": 100, "min": 1, "max": 1000},
{"type": "slider", "label": "Dropout", "event": "dropout", "min": 0, "max": 0.5, "step": 0.05, "value": 0.2},
{"type": "button", "label": "Train Model", "event": "train", "variant": "primary"}
]
}]
}
}
Data Filter Widget

Create filtering interfaces for dataframes:

json
{
"tool": "create_widget",
"arguments": {
"title": "Data Explorer",
"html": "<div id='preview'>Apply filters to see results</div>",
"height": 450,
"include_aggrid": true,
"toolbars": [{
"position": "inside",
"items": [
{"type": "multiselect", "label": "Columns", "event": "columns", "options": [
{"label": "Date", "value": "date"},
{"label": "Price", "value": "price"},
{"label": "Volume", "value": "volume"}
]},
{"type": "date", "label": "Start Date", "event": "start_date"},
{"type": "date", "label": "End Date", "event": "end_date"},
{"type": "button", "label": "Apply", "event": "apply", "variant": "primary"}
]
}]
}
}
Live Dashboard

For real-time updates, create a widget and periodically update it:

json
{
"tool": "create_widget",
"arguments": {
"title": "Live Metrics",
"html": "<div style='display:grid;grid-template-columns:1fr 1fr;gap:1rem;padding:1rem'><div id='metric1' style='padding:1rem;background:#1a1a2e;border-radius:8px'><h3>Accuracy</h3><p style='font-size:2rem'>--</p></div><div id='metric2' style='padding:1rem;background:#1a1a2e;border-radius:8px'><h3>Loss</h3><p style='font-size:2rem'>--</p></div></div>",
"height": 200
}
}

Update metrics with set_content:

json
{
"tool": "set_content",
"arguments": {
"widget_id": "abc123",
"component_id": "metric1",
"html": "<h3>Accuracy</h3><p style='font-size:2rem;color:#4ade80'>94.5%</p>"
}
}

Troubleshooting

AnyWidget Issues
  1. Ensure pip install 'pywry[notebook]' was run
  2. Restart the kernel after installing
  3. Check widget displays with just widget (not print(widget))
IFrame Issues
  1. Ensure the MCP server is running with PYWRY_HEADLESS=1
  2. Check the widget server is accessible at http://localhost:8765
  3. Verify the widget_id in the IFrame URL matches
Events Not Captured
  1. Ensure toolbar items have event properties set
  2. Use get_events with clear: false first to inspect without clearing
  3. Check that the widget_id is correct

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
89
Repository forks
7
7-day trend score
22

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/deeleeramone/pywry/jupyter/badge)](https://verified-skill.com/skills/deeleeramone/pywry/jupyter)

Something wrong with this skill or its page? Tell us.