diff --git a/docs/3.upgrading-to-v4.md b/docs/3.upgrading-to-v4.md index aa79273a18..c4f95d2b4d 100644 --- a/docs/3.upgrading-to-v4.md +++ b/docs/3.upgrading-to-v4.md @@ -130,6 +130,7 @@ The generic _open in editor_ action (from component and file links) is unaffecte - `vueDevTools` (default `true`) — set to `false` to skip the Vue DevTools dock. - `dataInspector` (default `true`) — set to `false` to skip the Data Inspector panel and its `Nuxt Application` source. - `disableAuthorization` (default: on in sandboxes) — skips the authorization prompt described above. +- `mcp` (default `'auto'`) — set to `false` to turn off the MCP endpoint that lets AI agents use DevTools. ## Deprecation warnings in your terminal diff --git a/docs/index.md b/docs/index.md index 182ccaf46e..86f3eae036 100644 --- a/docs/index.md +++ b/docs/index.md @@ -90,18 +90,19 @@ export default defineNuxtConfig({ }) ``` -| Option | Default | Description | -| ------------------------- | ------- | ----------------------------------------------------------------------------------------------------------- | -| `enabled` | `true` | Enable Nuxt DevTools. | -| `componentInspector` | `true` | Inspect the DOM to find the component rendering it. | -| `vueDevTools` | `true` | Register the Vue DevTools dock next to the `Nuxt` group. | -| `viteInspect` | `true` | Register the [Inspect](/modules/devtools/features#inspect) dock, or its install launcher. | -| `dataInspector` | `true` | Register the [Data Inspector](/modules/devtools/features#data-inspector) panel. | -| `codeServer` | | [Code Server](/modules/devtools/features#code-server) options; `codeServer.enabled: false` removes it. | -| `timeline` | | [Timeline](/modules/devtools/features#timeline) options; `timeline.enabled` defaults to `false`. | -| `assets.uploadExtensions` | | File extensions the [Assets](/modules/devtools/features#assets) panel accepts for upload, or `'*'` for any. | -| `disableAuthorization` | | Skip the browser authorization prompt. On by default in sandboxes. | -| `telemetry` | | Anonymous telemetry. Follows your Nuxt telemetry setting; set to `false` to opt out. | +| Option | Default | Description | +| ------------------------- | -------- | ------------------------------------------------------------------------------------------------------------- | +| `enabled` | `true` | Enable Nuxt DevTools. | +| `componentInspector` | `true` | Inspect the DOM to find the component rendering it. | +| `vueDevTools` | `true` | Register the Vue DevTools dock next to the `Nuxt` group. | +| `viteInspect` | `true` | Register the [Inspect](/modules/devtools/features#inspect) dock, or its install launcher. | +| `dataInspector` | `true` | Register the [Data Inspector](/modules/devtools/features#data-inspector) panel. | +| `codeServer` | | [Code Server](/modules/devtools/features#code-server) options; `codeServer.enabled: false` removes it. | +| `timeline` | | [Timeline](/modules/devtools/features#timeline) options; `timeline.enabled` defaults to `false`. | +| `assets.uploadExtensions` | | File extensions the [Assets](/modules/devtools/features#assets) panel accepts for upload, or `'*'` for any. | +| `disableAuthorization` | | Skip the browser authorization prompt. On by default in sandboxes. | +| `mcp` | `'auto'` | Expose the Vite DevTools [MCP](https://modelcontextprotocol.io) endpoint for AI agents; `false` turns it off. | +| `telemetry` | | Anonymous telemetry. Follows your Nuxt telemetry setting; set to `false` to opt out. | For every option, see the TSDocs in your IDE or the [type definition file](https://github.com/nuxt/devtools/blob/main/packages/devtools-kit/src/_types/options.ts). diff --git a/packages/devtools-kit/src/_types/options.ts b/packages/devtools-kit/src/_types/options.ts index ecaa2c6d32..798fa26c67 100644 --- a/packages/devtools-kit/src/_types/options.ts +++ b/packages/devtools-kit/src/_types/options.ts @@ -77,6 +77,22 @@ export interface ModuleOptions { */ disableAuthorization?: boolean + /** + * Expose the Vite DevTools MCP endpoint (`/__devtools/__mcp`), which + * lets AI agents call the DevTools' agent tools over the Model Context + * Protocol. + * + * - `'auto'`: mount the endpoint once any DevTools integration exposes an + * agent tool. + * - `true`: always mount it. + * - `false`: never mount it. + * + * Same as setting `vite.devtools.mcp`, which takes precedence. + * + * @default 'auto' + */ + mcp?: boolean | 'auto' + /** * Experimental features */ diff --git a/packages/devtools/src/module-main.ts b/packages/devtools/src/module-main.ts index 639079a5df..0acca022ad 100644 --- a/packages/devtools/src/module-main.ts +++ b/packages/devtools/src/module-main.ts @@ -69,14 +69,22 @@ export async function enableModule(options: ModuleOptions, nuxt: Nuxt) { await nuxt.callHook('devtools:before') + // Vite DevTools options Nuxt DevTools provides. They only fill in what the + // user left unset in `vite.devtools`, and are applied in one place below so + // both the Vite 8.3+ integration and the manual `DevTools()` plugin see them. + const viteDevToolsDefaults: DevToolsConfig = {} + // `disableAuthorization` disables the Vite DevTools client-auth prompt. The // resolved value is used (default `isSandboxed`), so sandboxes keep // auto-bypassing the prompt. - if (options.disableAuthorization) { - extendViteDevToolsConfig((devtools) => { - devtools.clientAuth ??= false - }) - } + if (options.disableAuthorization) + viteDevToolsDefaults.clientAuth = false + + // `mcp` controls the aggregate MCP endpoint (`__mcp`) Vite DevTools + // mounts over every devframe's agent tools. Left `undefined` it follows + // Vite DevTools' own default (`'auto'`). + if (options.mcp !== undefined) + viteDevToolsDefaults.mcp = options.mcp // Route the client-auth banner through Nuxt's terminal host where this Nuxt // has one (`useTerminal`, @nuxt/kit >= 4.6): the Nuxt CLI 4 TUI shows a @@ -86,10 +94,8 @@ export async function enableModule(options: ModuleOptions, nuxt: Nuxt) { const kit = await import('@nuxt/kit') if ('useTerminal' in kit) { const { banner, onTrusted } = createTerminalAuthBanner(kit.useTerminal) - extendViteDevToolsConfig((devtools) => { - devtools.banner ??= banner - devtools.onTrusted ??= onTrusted - }) + viteDevToolsDefaults.banner = banner + viteDevToolsDefaults.onTrusted = onTrusted } // Make unimport exposing more information, like the usage of each auto imported function @@ -160,18 +166,23 @@ export async function enableModule(options: ModuleOptions, nuxt: Nuxt) { windowTitle: 'Nuxt DevTools', } + viteDevToolsDefaults.branding = branding + // Vite 8.3+ registers the Vite DevTools integration itself from the // top-level `devtools` config option (vitejs/vite#23333), which keeps the // toggle in user hands (`vite: { devtools: false }` in `nuxt.config`). // Older Vite has no serve-mode integration, so fall back to installing the - // `DevTools()` plugin manually. + // `DevTools()` plugin manually. That plugin resolves its config from its own + // options and overwrites `config.devtools`, so the defaults must be passed + // to it directly. if (isGreaterThanOrEqual(viteVersion, '8.3.0')) { extendViteDevToolsConfig((devtools) => { - devtools.branding ??= branding + for (const [key, value] of Object.entries(viteDevToolsDefaults)) + (devtools as Record)[key] ??= value }) } else { - const DevTools = await import('@vitejs/devtools').then(r => r.DevTools({ branding })) + const DevTools = await import('@vitejs/devtools').then(r => r.DevTools(viteDevToolsDefaults)) addVitePlugin(DevTools) } diff --git a/skills-lock.json b/skills-lock.json index ac14d15a02..d7ce4f62b0 100644 --- a/skills-lock.json +++ b/skills-lock.json @@ -39,14 +39,14 @@ "source": "mattpocock/skills", "sourceType": "github", "skillPath": "skills/engineering/code-review/SKILL.md", - "computedHash": "57cfd4ceb011f05e58a1a4f4cad3b2e03419d371f8990f4bcb32ff0d435a039f", + "computedHash": "c2745e2be960b82b9fddd82cf45265f42431e7b045c403f297b25f0f311e9210", "via": "@antfu/skills" }, "codebase-design": { "source": "mattpocock/skills", "sourceType": "github", "skillPath": "skills/engineering/codebase-design/SKILL.md", - "computedHash": "b2888e4f4e8c0af3bfd557575a64b905c44e6248c3101d72077816882b3a92b9", + "computedHash": "aa11a96c08451f4ff86052d5da94004a8c97bb4ea41b2ac8a4300c189f66c89c", "via": "@antfu/skills" }, "create-adaptable-composable": { @@ -95,7 +95,7 @@ "source": "mattpocock/skills", "sourceType": "github", "skillPath": "skills/productivity/grilling/SKILL.md", - "computedHash": "ef1641a2047b71b60f1942cd35efb47d3afc9d584dff5a0b01f8c7db923aaa08", + "computedHash": "e40cc1d348f6d935e28f1e24474302d7368f0a400429271a43b35fe154891dc5", "via": "@antfu/skills" }, "handoff": { @@ -137,7 +137,7 @@ "source": "mattpocock/skills", "sourceType": "github", "skillPath": "skills/engineering/research/SKILL.md", - "computedHash": "c8c1cba327a6f824b554cd978079a3dadd7406d73174f8fb9bfef58824691970", + "computedHash": "5d85b64ecceed6b3f6d5996dc8af07180be8d1ff11ef3d26eda2acff078fbd39", "via": "@antfu/skills" }, "simple-english": {