The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the MCP VS Code listing page.
MCP VS Code runs a self-hosted Code OSS/OpenVSCode workbench beside an MCP server so the human and the model operate the same workspace, open editors, diagnostics, commands, extensions, and terminal sessions.
This is not remote control of a separately installed desktop VS Code. Supported distributions carry their own OpenVSCode runtime and bridge extension. Microsoft-hosted vscode.dev is not used because it disallows framing.
There are four pieces:
The default iframe and browser-tab paths deliver OpenVSCode directly. Experimental streaming launches an existing Edge, Chrome, or Chromium on the server, points it at that same OpenVSCode runtime, and transports its pixels and user input. The canvas is a remote display, not another editor implementation.
| Mode | Selection | Required host capability | What the user sees |
|---|---|---|---|
embedded | Default when the host approves the declared workbench origin and the liveness probe succeeds | frameDomains for the nested document | Genuine OpenVSCode inside the MCP App |
stream | Only when MCP_VSCODE_RENDER_MODE=stream | A reachable WebSocket allowed by connectDomains; no nested-frame grant | Genuine OpenVSCode rendered by server-side Chromium and drawn as pixels in the MCP App |
browser | Honest fallback when the requested inline mode is denied, unreachable, or unavailable | Host-supported openLink, or a normal link in the debug page | The same genuine OpenVSCode workbench in a separate tab |
probing is a temporary UI state, not a renderer.
With no render-mode environment variable, the App:
frameDomains reported by the host when that information is available;mcp-vscode:workbench-alive message;embedded only after that positive signal; orbrowser card with the exact policy, network, or runtime reason.A CSP-blocked iframe can emit neither a useful load nor error event, so a plain iframe event is not treated as success. The liveness timeout prevents a permanent blank view.
An MCP server's CSP declaration is a permission request, not a way to overrule the host. A host may approve it, restrict it, or deny it. CORS headers on mcp-vscode cannot repair a frame-src decision made by the outer host.
Set:
Streaming deliberately replaces the iframe decision for that process; it is not an automatic fallback. If streaming cannot start, the App reports the failure and moves to the honest browser option rather than silently selecting a different editor.
The server:
MCP_VSCODE_STREAM_BROWSER;node account from /etc/passwd, transfers ownership of that private profile, and drops only the Chromium child to its non-zero uid/gid;HOME, TMPDIR, and XDG directories into that same ephemeral profile instead of inheriting the server account's paths;127.0.0.1 only;The /stream WebSocket uses its own random 256-bit bearer token. Both the tokenized stream URL and the high-entropy /ide/<key> URL are excluded from model-visible tool text and structuredContent; they are delivered to the MCP App through tool-result _meta only. Logs do not contain the stream token.
Streaming is useful when a host grants connectDomains but refuses frameDomains, which is the behavior observed with locally configured Claude Desktop stdio connectors in the test documented in the upstream report draft.
Streaming remains experimental:
All three displayed outcomes refer to the real OpenVSCode runtime. If that runtime is missing or failed, there is no editor UI to show. File, Git, and terminal MCP tools may still operate where applicable, but editor/diagnostics/command/extension tools that require the live bridge fail explicitly.
There is no special macOS editor fallback: without an OpenVSCode Server runtime, neither embedding, streaming, nor the external-browser view can provide the workbench.
| Variable | Default | Purpose |
|---|---|---|
MCP_VSCODE_WORKSPACE | Process working directory | Absolute workspace root. Prefer setting this explicitly. --workspace takes precedence. |
MCP_VSCODE_OPENVSCODE_ROOT | Platform runtime package or bundled runtime | Override the OpenVSCode runtime directory. --openvscode-root takes precedence. |
MCP_VSCODE_RENDER_MODE | default | Set exactly stream to enable experimental genuine-workbench pixel streaming. default, empty, or unset uses iframe/browser behavior. Other values fail startup. |
MCP_VSCODE_STREAM_BROWSER | Auto-discovery | Absolute path to Edge, Chrome, or Chromium for streaming. |
MCP_VSCODE_STREAM_NO_SANDBOX | 0 | Set 1 or true only as an explicit last resort when a locked-down container cannot run Chromium's own sandbox. On POSIX, a root mcp-vscode process instead drops only Chromium to a safe node account by default. |
FLUJO-managed hosted children may also receive FLUJO_MCP_APP_RUNTIME_REGISTER_URL and FLUJO_MCP_APP_RUNTIME_REGISTER_TOKEN. Those are short-lived internal broker capabilities, not user settings. mcp-vscode proves possession, registers an allowlisted route manifest, clears both variables before OpenVSCode starts, and never exposes the bearer to the workbench.
Default mode honestly falls back to a browser when the tested Claude Desktop host declines the local loopback frameDomains request:
To test genuine inline streaming instead:
The browser-path override is optional when discovery finds an installed browser. Host behavior changes over time; re-run the manual matrix against the exact Claude Desktop version rather than treating the current observation as permanent.
A user can visit one human-facing site such as try.flujo.com.co, while the browser uses additional security origins behind the scenes. A sandboxed MCP App and its nested workbench cannot safely be collapsed into one literal browser origin merely to make deployment look simpler.
For a FLUJO-managed stdio child, the runtime-broker handshake solves the private-port problem:
/ide/<key> prefix, including the workbench's HTTP and WebSocket traffic./stream WebSocket route.127.0.0.1 to the visitor./mcp, /bridge, /healthz, /app, /session.json, and the temporary proof route private.The hosted deployment still needs:
/stream when experimental streaming is enabled;Upgrade, Host, Origin, and Referer behavior expected by the sandbox and workbench; andhttps: origin so the corresponding stream URL is wss:.For streaming on Fly, install Edge, Chrome, or Chromium in the Machine image. Prefer running the whole container unprivileged. If FLUJO must run mcp-vscode as root, the image must contain exactly one node account with a non-zero uid and gid and a safe shared /tmp (root-owned, traversable, and sticky when group/world-writable); mcp-vscode creates the high-entropy profile under that ancestor, chowns only the profile, and spawns only the browser under node with the sandbox intact. Missing or unsafe account/temp-directory data produces a visible streaming-unavailable error. It never silently adds --no-sandbox. MCP_VSCODE_STREAM_NO_SANDBOX=1 remains an explicit last-resort security tradeoff, not ordinary deployment configuration.
If mcp-vscode is deployed remotely without FLUJO's broker, --public-url must name an equivalent browser-reachable gateway origin and the reverse proxy must carry the same workbench HTTP/WebSocket and optional /stream WebSocket traffic. CORS settings alone cannot replace routing.
The local gateway serves:
| Route | Authentication/exposure | Purpose |
|---|---|---|
GET /healthz | Local deployment policy | Liveness and OpenVSCode/bridge state |
GET /session.json | ?token= when --auth-token is configured | Debug-browser session payload |
GET /app | ?token= when --auth-token is configured | Debug version of the MCP App document |
ALL /mcp | Authorization: Bearer when configured | Streamable HTTP MCP transport |
HTTP/WS /ide/<random>/... | High-entropy per-process path; narrowly brokered in FLUJO | Proxied genuine OpenVSCode workbench, assets, APIs, and sockets |
WS /bridge | Authenticated bridge handshake | OpenVSCode bridge extension JSON-RPC channel; not brokered publicly by FLUJO |
WS /stream | Independent token in query; one viewer; only when enabled | Experimental JPEG-frame and input channel |
GET /.well-known/flujo/mcp-app-runtime | Temporary one-use FLUJO proof; then disabled | Hosted runtime registration only |
The brokered public origin exposes only the routes explicitly registered for the MCP App, not this entire local surface.
vscode_execute_command escape hatch for commands registered in the live workbench.The server exposes 27 tools across these groups:
| Group | Tools |
|---|---|
| App/session | vscode_open, workspace_status |
| Files | fs_list, fs_read, fs_write, fs_delete, fs_move, fs_search |
| Editor | editor_open, editor_state, editor_set_selection, editor_apply_edits |
| Language services | diagnostics_get |
| Commands | vscode_list_commands, vscode_execute_command |
| Extensions | extensions_list, extensions_install, extensions_uninstall |
| Terminals | terminal_create, terminal_list, terminal_read, terminal_write, terminal_resize, terminal_kill |
| Git | git_status, git_diff, git_run |
Editor, diagnostics, command, and extension tools always target the genuine OpenVSCode bridge. Destructive and open-world tools are annotated so compatible MCP hosts can apply their approval policy.
Download and extract the release archive for your platform.
Windows x64:
Linux x64 or ARM64:
The archive contains its own Node.js and OpenVSCode runtimes. Default iframe/browser operation does not require VS Code, Node.js, Docker, or a system-wide package installation. Experimental streaming additionally requires an installed Chromium-family browser.
With Node.js 22 or newer, npx starts the bundled stdio server on Windows x64, Linux x64, and Linux ARM64:
Pin the workspace explicitly. Without --workspace or MCP_VSCODE_WORKSPACE, the server uses its process working directory and reports that choice on stderr. Do not accidentally expose a home directory, volume root, or unrelated checkout.
@mario.andreschak/mcp-vscode declares optional platform packages for Windows x64, Linux x64, and Linux ARM64, so npm downloads only the matching OpenVSCode runtime. No Darwin runtime package is published.
Calling vscode_open opens the MCP App. The Fullscreen button requests the host's fullscreen display mode; the host decides whether to grant it.
The MCP endpoint is https://editor.example.com:8443/mcp. Binding beyond loopback is rejected unless both TLS and a bearer token are configured. A TLS-terminating reverse proxy may instead front a loopback HTTP child, but its public URL and WebSocket routing must be correct.
The host must support the stable MCP Apps extension io.modelcontextprotocol/ui and text/html;profile=mcp-app resources.
For default inline embedding it must honor the declared frameDomains and permit the framed workbench's own scripts, workers, service workers, assets, and WebSockets. The current MCP App bundle is self-contained, so it does not request resourceDomains; that grant would cover resources loaded directly by the App and would not authorize a nested workbench frame. If the host restricts the frame grant, the App reports that decision and offers the browser path.
For experimental streaming it must permit the declared gateway WebSocket through connectDomains, preserve tool-result _meta for the App, and support ordinary canvas image decoding. Streaming does not require frameDomains.
Requirements for development: Node.js 22+. A system Chromium-family browser is optional and is used only by the real streaming integration test when present.
Useful commands:
npm run typecheck covers the Node server, MCP App browser code, and bridge extension. npm test exercises unit/security policy, while npm run test:integration includes the gateway and real system-browser screencast smoke test (skipped when no browser is installed).
The runtime fetcher pins OpenVSCode 1.109.5 and verifies upstream Linux SHA-256 digests before extraction. Windows builds pin the configured upstream commit and invoke Code OSS's Windows remote-web build target. Runtime and standalone output directories are ignored by Git.
Release Please maintains a release pull request from conventional commits (fix:, feat:, and breaking type!: changes). Merging that pull request creates the next v* tag and GitHub Release. The tag starts Release CI, which builds all platform artifacts and publishes the runtime packages before the platform-neutral dispatcher through npm trusted publishing. Normal releases require no local artifacts, npm token, npm login, or browser authentication.
Release Please uses a repository-scoped GitHub App so the tag it creates can trigger Release CI. Configure the App once with Contents, Issues, and Pull requests read/write access, install it only on this repository, then add:
RELEASE_APP_CLIENT_ID — the App's Client ID;RELEASE_APP_PRIVATE_KEY — the App's PEM private key.Without those values, the Release Please workflow exits successfully with a configuration notice and performs no release operation. The npm side remains secretless: each package trusts .github/workflows/release.yml in flujo-app/mcp-vscode-mcpapp, restricted to the npm-publish environment.
Routine release flow:
main with a conventional squash title.npm run npm:publish is only for verifying or resuming previously built GitHub Release artifacts. It does not build or download them:
Useful authentication commands:
The publish script verifies artifact hashes and internal package names/versions before authentication. It skips only registry versions whose tarball integrity matches exactly, so interrupted runs are resumable; it does not rebuild the audited tarballs. It also refuses to move a dist-tag such as latest or beta backward if an older failed release is retried after a newer one.
The MCP Registry stores metadata only, so the npm package must already be live:
The script checks package.json, server.json, the published npm metadata, namespace authorization, and the pinned publisher binary before upload. Registry versions are immutable; existing versions are skipped unless --force is passed.
Authentication options include:
node uid/gid; its HOME and XDG paths are confined to that ephemeral profile.MCP_VSCODE_STREAM_NO_SANDBOX=1 weakens defense in depth and should not be the default answer to a container configuration problem.git_run; arbitrary VS Code commands, extension installation, and shell input remain powerful and should require host approval.See SECURITY.md for reporting and deployment guidance.
OpenVSCode Server and Code OSS are MIT-licensed upstream projects. MCP VS Code is independent and is not affiliated with or endorsed by Microsoft or Gitpod. “Visual Studio Code” and “VS Code” are trademarks of Microsoft Corporation.
MIT. See LICENSE and THIRD_PARTY_NOTICES.md.