MCP server
@qwik.dev/mcp connects an MCP client to a running Qwik development server. It supports browser rendering and Router SSR and works independently of the DevTools panel.
Setup
pnpm add -D @qwik.dev/mcp
Add qwikMcp() before qwikVite() in vite.config.ts:
import { defineConfig } from 'vite';
import { qwikVite } from '@qwik.dev/core/optimizer';
import { qwikRouter } from '@qwik.dev/router/vite';
import { qwikMcp } from '@qwik.dev/mcp';
export default defineConfig({
plugins: [qwikMcp(), qwikRouter(), qwikVite()],
});
For a browser-only Qwik app, omit qwikRouter() and keep your existing qwikVite({ csr: true }) configuration. Start Vite and open the app in a local browser.
MCP client configuration
The examples below run the installed package directly with Node.js 22.18 or later. They use the same package version as your Vite plugin, require no download at startup, and work even when the client starts the process outside your project directory.
Replace /absolute/path/to/project with the directory containing your app's vite.config.ts and node_modules. The first argument points to the installed CLI; the second selects the Qwik project. Passing only the project path to npx --no-install does not change where npm looks for the local package.
Codex
Add this to .codex/config.toml in your project:
[mcp_servers.qwik]
command = "node"
args = ["/absolute/path/to/project/node_modules/@qwik.dev/mcp/dist/cli.js", "/absolute/path/to/project"]
Codex loads project configuration for trusted projects. You can also add the entry to ~/.codex/config.toml for a personal configuration. Restart your Codex session after editing the file; in the CLI, use /mcp to check the connection. See the Codex MCP documentation.
Claude Code
Create .mcp.json in your project root:
{
"mcpServers": {
"qwik": {
"type": "stdio",
"command": "node",
"args": [
"/absolute/path/to/project/node_modules/@qwik.dev/mcp/dist/cli.js",
"/absolute/path/to/project"
]
}
}
}
Start Claude Code in the project, approve the project MCP server when prompted, and use /mcp to check its status. See the Claude Code MCP documentation.
GitHub Copilot in VS Code
Create or update .vscode/mcp.json:
{
"servers": {
"qwik": {
"type": "stdio",
"command": "node",
"args": ["${workspaceFolder}/node_modules/@qwik.dev/mcp/dist/cli.js", "${workspaceFolder}"]
}
}
}
VS Code replaces ${workspaceFolder} with the project directory. This format uses servers, whereas Claude Code uses mcpServers. Run MCP: List Servers from the Command Palette, select qwik, and start it. In Copilot Chat, select Agent mode and enable the Qwik tools in the tools picker. See the VS Code MCP documentation.
Check the connection
Ask your agent to call get_project_info and confirm that root is your app directory. devServerRunning: false means the CLI connected but Vite is not running with qwikMcp(). Start Vite and open the app in a browser to use the live inspection tools.
If the client cannot find node, set command to the absolute path of your Node.js executable. If it cannot find cli.js, check that @qwik.dev/mcp is installed in the selected project. On Windows, use forward slashes in paths, such as C:/projects/my-app, or escape each backslash as \\ in JSON and TOML strings.
Tools
| Tool | Inputs | Result |
|---|---|---|
get_project_info | {} | Installed versions, script names, documentation match and optional dev URL |
list_routes | {} | routerInstalled and Router's routes, source files, parameters, layouts |
get_dev_errors | { url? } | Vite errors observed by the selected page, with source locations |
inspect_page | { url?, selector?, includeHtml?, includeSignalValues?, includeSerializedState?, includeSerializedVNodeTree?, offset? } | Component tree, hooks, optional HTML, signal values, parsed state and VNode tree |
search_docs | { query, limit? } | Ranked documentation page IDs, titles, snippets and snapshot version |
get_doc | { id } | Full Markdown page, source URL and snapshot version |
get_best_practices | {} | Short Qwik coding guide and its bundled version |
includeHtml and includeSignalValues default to false. selector scopes the HTML fragment; component metadata still describes the page. HTML is current DOM, marked source: "live-dom", limited to 64 KiB of UTF-8, with truncated indicating an incomplete fragment. It is not the original SSR response.
includeSerializedState and includeSerializedVNodeTree also default to false. They parse the page's Qwik state scripts and reconstruct a VNode tree from a copy of the DOM. Each returns null when no Qwik container or relevant state exists, or { source: "serialized-dom", content, truncated, nextOffset } with a 64 KiB UTF-8 limit. These snapshots may differ from current signal values after interaction. selector does not scope them.
Each text result also includes nextOffset. If truncated is true, call inspect_page again with the same include flag and offset: nextOffset. Repeat until nextOffset is null. The offset counts UTF-8 bytes and applies to every selected text field, so request one text field at a time when paging. Page changes can mix snapshots across calls; if an offset becomes invalid, restart at 0.
Hook metadata is collected by the shared DevTools instrumentation as components execute and their document-ready tasks run. Components that have not executed in the browser may appear in the tree without hook metadata. Snapshot entries are grouped by component source, so repeated instances share that metadata.
With several pages connected, provide the exact page URL. Duplicate tabs with the same URL must be closed until one remains. Missing pages, invalid selectors, missing runtime and disconnected servers return tool errors. Vite errors clear after successful HMR; this is not a project-wide typecheck or build report.
Offline documentation
get_best_practices, search_docs and get_doc work without Vite, an open browser or network access. The short guide and documentation snapshot are bundled with the MCP package and carry its version. The snapshot is generated from all Qwik documentation and API pages during the MCP build. MCP uses the same complete manifest as llms.txt; new documentation pages are discovered automatically during the build. It describes that release, which may differ from the Qwik version installed in your application.
The MCP server also sends workflow instructions during initialization: read the guide for Qwik code, search for specific topics, then fetch the full page. The instructions describe which live tools require Vite and a connected browser.
get_project_info reads installed Qwik packages and project script names even when Vite is stopped. It returns documentation.version and documentation.matchesProject, which compares the bundled documentation version with the installed Qwik core version exactly. devServerRunning is false and devUrl is absent until Vite starts. routerVersion reports the installed Router package; use list_routes to see whether the Router plugin is active.
Search first, then use a returned page ID to read the full document:
{ "query": "useSignal", "limit": 5 }
{ "id": "/docs/core/state/" }
Search matches words in page titles, descriptions and Markdown content, with title matches ranked first. limit defaults to 5 and accepts 1–20. An unknown page ID returns a tool error.
Local access
The plugin runs only during development. Its internal endpoint accepts loopback connections with a random session token and rejects browser origins. Discovery files live in node_modules/.cache/qwik-mcp, have owner-only permissions on Unix, and are removed when the server closes. Stale files from terminated processes are ignored.
Use a standalone HTTP Vite server with HMR enabled. HTTPS and middleware mode are currently unsupported. The CLI sends only MCP protocol messages to stdout. Tools inspect the running app and do not edit files, install packages or start builds. Returned HTML, hook metadata and signal values are application content and may contain private information.