Feature/#812 implement vscode extension and mcp#831
Conversation
…unch configuration
There was a problem hiding this comment.
Pull request overview
Implements the QuickMock VS Code extension (custom editor + MCP integration) and adds an MCP server package with headless wireframe rendering support, closing #812.
Changes:
- Added a VS Code custom editor for
.qmfiles backed by a webview-hosted QuickMock app, plus a webview bridge protocol. - Added an MCP server (tools for listing/reading/rendering wireframes, headless screenshots via Puppeteer) and extension-side MCP registration/definition provider.
- Updated build/configuration to bundle webview assets, copy MCP artifacts into the extension, and introduce new shared protocol utilities.
Reviewed changes
Copilot reviewed 80 out of 81 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| tooling/typescript/node.json | Adds Node types to the shared TS node config. |
| packages/vscode-extension/tsdown.config.ts | Splits bundling into extension (CJS) and webview (IIFE) outputs. |
| packages/vscode-extension/tsconfig.json | Adds DOM lib to support webview TS sources. |
| packages/vscode-extension/src/webview/main.ts | Boots the webview iframe and initializes the bridge. |
| packages/vscode-extension/src/webview/bridge.ts | Forwards postMessage traffic between iframe ↔ extension. |
| packages/vscode-extension/src/mcp/server-definition-provider.ts | Registers a dynamic MCP server definition provider in VS Code. |
| packages/vscode-extension/src/mcp/registry-server.ts | Adds a local registry HTTP server for live document content. |
| packages/vscode-extension/src/mcp/mcp-registration.ts | Implements MCP registration across VS Code and other client config files. |
| packages/vscode-extension/src/mcp/mcp-config-file.ts | Reads/writes MCP JSON config files for external clients. |
| packages/vscode-extension/src/mcp/mcp-command.ts | Adds a command UX for MCP registration and inspection. |
| packages/vscode-extension/src/mcp/mcp-client-targets.ts | Detects MCP client config locations across OSes. |
| packages/vscode-extension/src/index.ts | Wires activation: editor provider, registry server, MCP provider/registration. |
| packages/vscode-extension/src/editor/provider.ts | Implements CustomEditorProvider for .qm documents. |
| packages/vscode-extension/src/editor/panel.ts | Generates webview HTML/CSP and injects app URL for iframe. |
| packages/vscode-extension/src/editor/handlers.ts | Handles webview messages (load/save) and file I/O. |
| packages/vscode-extension/src/editor/document.ts | Implements document open/read/write helpers. |
| packages/vscode-extension/src/core/paths.ts | Centralizes extension paths (MCP entrypoint, app-url file). |
| packages/vscode-extension/src/core/logger.ts | Adds basic logging helpers for the extension runtime. |
| packages/vscode-extension/src/core/document-registry.ts | Tracks in-memory document contents for MCP consumption. |
| packages/vscode-extension/src/core/config.ts | Adds quickmock.appUrl config + writes headless app URL to disk. |
| packages/vscode-extension/scripts/copy-mcp.mjs | Copies MCP package dist into the extension dist on build. |
| packages/vscode-extension/package.json | Adds activation/events, commands, custom editor, MCP contributions, build pipeline. |
| packages/vscode-extension/.vscodeignore | Excludes scripts/env/vsix from VSIX packaging. |
| packages/mcp/tsdown.config.ts | Forces bundling all deps for the MCP server distribution. |
| packages/mcp/tsconfig.json | Adds DOM lib for renderer-related code. |
| packages/mcp/src/tools/list-wireframes/list-wireframes.tool.ts | Defines the list_wireframes MCP tool. |
| packages/mcp/src/tools/list-wireframes/list-wireframes.handler.ts | Implements workspace scan for .qm files. |
| packages/mcp/src/tools/list-wireframes/index.ts | Re-exports list wireframes tool. |
| packages/mcp/src/tools/get-wireframe-pages/index.ts | Re-exports get wireframe pages tool. |
| packages/mcp/src/tools/get-wireframe-pages/get-wireframe-pages.tool.ts | Defines the get_wireframe_pages MCP tool. |
| packages/mcp/src/tools/get-wireframe-pages/get-wireframe-pages.schema.ts | Adds Zod schema for get wireframe pages. |
| packages/mcp/src/tools/get-wireframe-pages/get-wireframe-pages.models.ts | Adds wireframe page model for tool output. |
| packages/mcp/src/tools/get-wireframe-pages/get-wireframe-pages.handler.ts | Implements page metadata extraction from .qm files. |
| packages/mcp/src/tools/get-wireframe-json/index.ts | Re-exports get wireframe JSON tool. |
| packages/mcp/src/tools/get-wireframe-json/get-wireframe-json.tool.ts | Defines the get_wireframe_json MCP tool. |
| packages/mcp/src/tools/get-wireframe-json/get-wireframe-json.schema.ts | Adds Zod schema for get wireframe JSON. |
| packages/mcp/src/tools/get-wireframe-json/get-wireframe-json.handler.ts | Implements JSON retrieval (registry-first, disk fallback). |
| packages/mcp/src/tools/get-wireframe-assets/index.ts | Re-exports get wireframe assets tool. |
| packages/mcp/src/tools/get-wireframe-assets/get-wireframe-assets.tool.ts | Defines the get_wireframe_assets MCP tool. |
| packages/mcp/src/tools/get-wireframe-assets/get-wireframe-assets.schema.ts | Adds Zod schema for asset extraction options. |
| packages/mcp/src/tools/get-wireframe-assets/get-wireframe-assets.models.ts | Adds wireframe asset model. |
| packages/mcp/src/tools/get-wireframe-assets/get-wireframe-assets.handler.ts | Extracts embedded image assets to disk and reports results. |
| packages/mcp/src/tools/capture-wireframe/index.ts | Re-exports capture wireframe tool. |
| packages/mcp/src/tools/capture-wireframe/capture-wireframe.tool.ts | Defines the capture_wireframe MCP tool. |
| packages/mcp/src/tools/capture-wireframe/capture-wireframe.schema.ts | Adds Zod schema for capture options. |
| packages/mcp/src/tools/capture-wireframe/capture-wireframe.handler.ts | Implements headless screenshot capture using the renderer. |
| packages/mcp/src/renderer/renderer.consts.ts | Adds renderer timeouts and local-instance hint string. |
| packages/mcp/src/renderer/page.session.ts | Implements Puppeteer page session (ready, send file, render complete, screenshot). |
| packages/mcp/src/renderer/index.ts | Re-exports renderer entrypoints. |
| packages/mcp/src/renderer/headless.renderer.ts | Launches Chromium and orchestrates end-to-end rendering flow. |
| packages/mcp/src/renderer/chromium.resolver.ts | Downloads/resolves a Chromium executable via @puppeteer/browsers. |
| packages/mcp/src/renderer/bridge.server.ts | Serves a local HTML bridge page for Puppeteer ↔ iframe messaging. |
| packages/mcp/src/renderer/app-url.consts.ts | Reads headless app URL from ~/.quickmock/app-url with default fallback. |
| packages/mcp/src/index.ts | Implements the MCP server process and registers all tools. |
| packages/mcp/src/core/registry.utils.ts | Adds workspace hashing used for registry server discovery. |
| packages/mcp/src/core/registry.models.ts | Defines registry client interface and null implementation. |
| packages/mcp/src/core/registry.client.ts | Implements registry HTTP client to fetch live doc content. |
| packages/mcp/src/core/mcp.logger.ts | Adds MCP-side logging helpers. |
| packages/mcp/src/core/index.ts | Re-exports MCP core utilities. |
| packages/mcp/src/commons/wireframe-file.service.ts | Adds a service wrapper for reading .qm files via registry/disk. |
| packages/mcp/src/commons/tool-response.helpers.ts | Adds helper builders for MCP tool responses (text/image/errors). |
| packages/mcp/src/commons/qm-file.utils.ts | Adds .qm read/parse logic with registry-first behavior. |
| packages/mcp/src/commons/qm-file.models.ts | Defines .qm file/page/shape contract models. |
| packages/mcp/package.json | Adds MCP runtime deps (MCP SDK, Puppeteer, Zod) and an inspector script. |
| packages/bridge-protocol/tsconfig.json | Adds TS config for the shared bridge protocol package. |
| packages/bridge-protocol/src/index.ts | Defines shared postMessage protocol types/constants. |
| packages/bridge-protocol/package.json | Adds the (private) workspace package for bridge protocol sharing. |
| package-lock.json | Updates lockfile for new workspace packages and new MCP/renderer dependencies. |
| apps/web/src/scenes/main.scene.tsx | Adds headless mode rendering path (Canvas-only) for screenshots. |
| apps/web/src/core/vscode/vscode-sync.utils.ts | Adds serialize/deserialize helpers for VS Code sync. |
| apps/web/src/core/vscode/use-vscode-sync.hook.ts | Adds top-level hook that wires all VS Code bridge behaviors. |
| apps/web/src/core/vscode/use-vscode-file-load.hook.ts | Implements LOAD_FILE handling and READY/WEBVIEW_READY handshake. |
| apps/web/src/core/vscode/use-vscode-auto-save.hook.ts | Implements debounced SAVE messages back to the extension. |
| apps/web/src/core/vscode/use-headless-render-complete.hook.ts | Emits RENDER_COMPLETE with computed bounding box for cropping. |
| apps/web/src/common/utils/vscode-bridge.utils.ts | Adds client-side message bus utilities for iframe ↔ webview comms. |
| apps/web/src/common/utils/env.utils.ts | Adds env/headless detection via query params. |
| apps/web/src/common/utils/compute-content-bbox.utils.ts | Computes content bounding box for renderer cropping. |
| apps/web/src/App.tsx | Enables VS Code sync hook at app startup. |
| apps/web/package.json | Adds dependency on the shared bridge protocol package. |
| .vscode/settings.json | Adds workspace setting for quickmock.appUrl (local dev URL). |
| .changeset/quick-meals-send.md | Adds release notes/changeset for the extension and MCP server. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Messages coming DOWN from Puppeteer (page.evaluate) → forward to iframe | ||
| if (iframe.contentWindow) { | ||
| iframe.contentWindow.postMessage(event.data, '*') | ||
| } |
There was a problem hiding this comment.
This bridge forwards Puppeteer → iframe messages using postMessage(..., '*'). Since the iframe URL is known (QUICKMOCK_URL), restrict the targetOrigin to that origin to prevent message leakage if the iframe is ever navigated elsewhere.
| const BROWSER_LAUNCH_ARGS = [ | ||
| '--no-sandbox', | ||
| '--disable-setuid-sandbox', | ||
| '--disable-web-security', | ||
| '--disable-features=IsolateOrigins,site-per-process', |
There was a problem hiding this comment.
The Chromium launch args include --no-sandbox, --disable-web-security, and --disable-features=IsolateOrigins,site-per-process, which significantly weaken isolation when loading remote content. If these flags aren't strictly required for rendering, remove them; if they are required, document why and keep the minimal necessary subset.
| const path = url.searchParams.get('path'); | ||
| if (!path) { | ||
| res.writeHead(400); | ||
| res.end('Missing path parameter'); | ||
| return; |
There was a problem hiding this comment.
The registry HTTP server exposes in-memory document contents on 127.0.0.1 with no authentication. Since the port is discoverable via the tmp .port file, consider adding a shared secret (written alongside the port) and requiring it via a header/query param to mitigate local-process data exfiltration.
| const iframe = document.createElement('iframe'); | ||
| iframe.src = appUrl; | ||
| iframe.allow = 'clipboard-read; clipboard-write'; | ||
| iframe.title = 'QuickMock Application'; | ||
| document.body.appendChild(iframe); |
There was a problem hiding this comment.
The embedded QuickMock app iframe is created without a sandbox attribute. Since this can load a configurable remote origin, consider adding a sandbox with the minimal required allowances (e.g. scripts/forms/same-origin as needed) to reduce the impact of a compromised/incorrect appUrl.
| }, | ||
| "quickmock.appUrl": "http://localhost:5173/editor.html" |
There was a problem hiding this comment.
This workspace-level VS Code setting forces quickmock.appUrl to a localhost dev server for everyone who opens the repo. That’s likely to break the extension/editor unless the dev server is running. Consider removing this from source control or moving it to a documented example (e.g. .vscode/settings.example.json).
| }, | |
| "quickmock.appUrl": "http://localhost:5173/editor.html" | |
| } |
| const PREFIX = '[quickmock-mcp]'; | ||
|
|
||
| export const logInfo = (message: string, ...rest: unknown[]): void => { | ||
| console.error(`${PREFIX} ${message}`, ...rest); |
There was a problem hiding this comment.
logInfo currently logs using console.error, which will mark normal informational output as errors and can confuse users/telemetry. Switch this to console.info (or console.log) so info and error logs are correctly separated.
| console.error(`${PREFIX} ${message}`, ...rest); | |
| console.info(`${PREFIX} ${message}`, ...rest); |
| return toolError( | ||
| `Error capturing wireframe at "${path} with ${QUICKMOCK_URL}": ${String(err)}` | ||
| ); |
There was a problem hiding this comment.
The error message string here has mismatched quotes/formatting: it currently interpolates path and QUICKMOCK_URL inside the same opening quote, which will render oddly and makes the path ambiguous. Adjust the message to quote the path and URL separately (e.g. ... at "${path}" with ${QUICKMOCK_URL}: ...).
| const iframe = document.querySelector('iframe') as HTMLIFrameElement; | ||
| iframe.contentWindow?.postMessage( | ||
| { type: 'LOAD_FILE', payload: { data: JSON.parse(content), fileName } }, | ||
| '*' | ||
| ); |
There was a problem hiding this comment.
postMessage is sent to the QuickMock iframe with targetOrigin: '*'. Since QM_APP_ORIGIN is available in this module, use it as the targetOrigin to avoid sending wireframe contents to an unexpected origin if the iframe URL changes or is navigated.
…d vscode extension
… export downloads
| { | ||
| ...baseTsdownConfig, | ||
| entry: ['src/index.ts'], | ||
| format: 'cjs', |
There was a problem hiding this comment.
Why you have to chage to cjs? It should works with es modules
…ants for communication
…rt and improve build settings
| "title": "QuickMock: New Wireframe" | ||
| }, | ||
| { | ||
| "command": "quickmock.connectMcp", |
…pt; adjust build configurations
Close #812