| name | qt-to-auroraview-migration |
| description | Convert an existing Qt/PySide/PyQt desktop project (QWebEngineView-based UI, QMainWindow browsers, Qt DCC tools) into an AuroraView project so it ships a lighter, Rust-powered WebView and gets full MCP automation for free. Use this skill whenever the user asks to "migrate", "convert", "port" a Qt/PySide/PyQt app to AuroraView, or when they want MCP-controllable Qt tooling. |
Qt → AuroraView migration skill
This skill turns an existing Qt-based Python project (typically one that uses
QWebEngineView, a custom QMainWindow, or a DCC tool dialog with embedded HTML)
into an AuroraView project with:
- A native Rust-powered WebView (~5 MB vs ~120 MB Qt WebEngine)
- Unified
create_webview() entry point (standalone / Qt parent / HWND)
- Bidirectional Python ↔ JavaScript bridge (
webview.emit / @webview.on)
- Full MCP control out of the box via
dcc-mcp-core's gateway — every
AuroraView window registers itself into the gateway and exposes a CDP bridge,
so agents can click, fill, screenshot, and call Python APIs over standard MCP
without the user writing any Python glue
When to use this skill
Use it when you see any of these signals in the source project:
from PySide6.QtWebEngineWidgets import QWebEngineView (or PySide2 / PyQt5 / PyQt6)
QWebChannel + registerObject for JS↔Python IPC
- A DCC-embedded Qt dialog that loads an HTML/React/Vue frontend
- A
QMainWindow whose central widget is basically a browser
- The user says "convert/migrate/port this Qt tool to AuroraView" or
"I want to control this Qt app with MCP"
Decision tree
Is there a QWidget parent (Maya/Houdini/Nuke/3ds Max)?
├── Yes → use QtWebView path (create_webview(parent=qwidget, ...))
└── No
├── Is there a native HWND (Unreal, C++ host)?
│ └── Yes → use HWND path (create_webview(parent=hwnd, ...))
└── No → standalone (create_webview(url=..., ...))
All three paths return the same WebView API; only the parent argument differs.
Migration playbook
Perform these steps in order. Each has a concrete before/after snippet so you
can grep-and-replace safely.
Step 1 — Dependencies
Replace Qt WebEngine with AuroraView. Keep qtpy / a Qt binding only if the
tool still needs Qt widgets around the webview (toolbars, dock panels, DCC
integration).
"auroraview>=0.4.19"
"auroraview[qt]>=0.4.19"
Step 2 — Replace QWebEngineView
from PySide6.QtWebEngineWidgets import QWebEngineView
from PySide6.QtCore import QUrl
view = QWebEngineView(parent)
view.setUrl(QUrl("http://localhost:3000"))
view.show()
from auroraview import create_webview
webview = create_webview(parent=parent, url="http://localhost:3000")
webview.show()
When there is no Qt parent, pass nothing:
webview = create_webview(url="http://localhost:3000", title="My Tool")
webview.show()
Step 3 — Replace QWebChannel IPC
AuroraView ships a first-class bridge — drop QWebChannel, registerObject,
and the custom JS adapter entirely.
from PySide6.QtWebChannel import QWebChannel
class Bridge(QObject):
@Slot(dict, result=dict)
def export_scene(self, data):
...
channel = QWebChannel(view.page())
channel.registerObject("bridge", Bridge())
view.page().setWebChannel(channel)
@webview.on("export_scene")
def handle_export(data):
return {"ok": True, "path": data["path"]}
webview.emit("scene_updated", {"frame": 120})
On the JS side, replace the qtwebchannel.js adapter with the AuroraView SDK:
new QWebChannel(qt.webChannelTransport, (channel) => {
channel.objects.bridge.export_scene({ path });
});
import { av } from "@auroraview/sdk";
await av.call("export_scene", { path });
av.on("scene_updated", (data) => console.log(data));
Step 4 — Replace QMainWindow browser shells
If the project is a custom browser (tabs, URL bar, history), keep the Qt chrome
but swap every QWebEngineView for AuroraView. The @examples/qt_browser.py
file in this repo is the before; here is the AFTER pattern:
from auroraview import create_webview
class BrowserTab(QWidget):
def __init__(self, url: str, parent=None):
super().__init__(parent)
layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
self.webview = create_webview(parent=self, url=url)
layout.addWidget(self.webview.widget())
Note: for native tab switching/reloading, call webview.load_url(...),
webview.reload(), webview.back(), webview.forward().
Step 5 — DCC integration (Maya / Houdini / Nuke / 3ds Max)
Thread-dispatcher backends are already bundled. The migration is literally:
ptr = omui.MQtUtil.mainWindow()
parent = wrapInstance(int(ptr), QWidget)
view = QWebEngineView(parent)
view.setUrl(QUrl("http://tool"))
from auroraview import create_webview
webview = create_webview(parent=parent, url="http://tool")
For non-Qt DCCs (Unreal) pass the HWND as an int:
webview = create_webview(parent=unreal_hwnd, url="http://tool")
hwnd = webview.get_hwnd()
Step 6 — Enable MCP control (the "for free" part)
Once the app is on AuroraView, agents drive it over MCP with zero extra
code on the project side. AuroraView windows register themselves into the
shared dcc-mcp-core gateway and expose their CDP endpoint automatically;
agents discover them and call tools through the gateway.
pip install dcc-mcp-core
auroraview-cli skills install --target cursor
python my_tool.py
Agents see tools exposed through dcc-mcp-core's progressive discovery —
tools/list stays small because the gateway hides detail-level tools behind
load_skill. For AuroraView the shipped skills are:
| Skill | Tools (visible by default / after load_skill) |
|---|
auroraview-diagnostics | list_windows, cdp_health, dump_console (implicit-invocation on) |
auroraview-devtools | evaluate_js, reload, capture_screenshot (explicit load_skill) |
See Epic #364 for the
rollout status — the Rust adapter crate (crates/auroraview-mcp) and the
skills listed above are tracked under issues #365–#368.
To expose custom Python methods to agents, decorate them and bind via
auroraview.api:
from auroraview import create_webview, api
class ToolAPI:
def rename_selected(self, prefix: str = "av_") -> dict:
...
def export_scene(self, path: str) -> dict:
...
webview = create_webview(parent=parent, url="http://tool")
api.bind(webview, ToolAPI())
One-shot migration checklist
Use this checklist when applying the skill to a repo. Tick every item.
References (read these on demand)
python/auroraview/api.py — unified create_webview() contract
python/auroraview/__init__.py — full public API surface
python/auroraview/integration/qt/ — Qt embedding internals
examples/qt_browser.py — canonical BEFORE example (pure Qt WebEngine)
examples/maya_qt_echo_demo.py — canonical AFTER example (Qt host + AuroraView + API bridge)
packages/auroraview-sdk/ — JS-side bridge (@auroraview/sdk)
crates/auroraview-mcp/ — Rust adapter crate that plugs AuroraView into
dcc-mcp-core's gateway (tracks Epic #364; part of the new MCP story)
dcc-mcp-core upstream — gateway,
skill runtime, and progressive tool discovery; MCP tools ship as SKILL.md
packages delivered via auroraview-cli skills install
Troubleshooting
| Symptom | Likely cause | Fix |
|---|
RuntimeError: No Qt binding found | qtpy can't resolve a binding | Install PySide6 (or pass parent=None for standalone) |
| Window shows but DCC freezes | Using WebView directly in a Qt host | Switch to create_webview(parent=qwidget) which picks QtWebView |
discover_instances returns empty list | WebView was started with debug=False | Leave debug=True (default) so the CDP port opens |
JS av.call() hangs | Python handler raised without returning JSON-serializable | Return a plain dict / list / str |
MCP click(selector=...) fails | Page not selected | Call select_page(url_pattern=...) first |