# Dusk MCP Setup The dusk MCP tools ride on the substrate MCP server shipped inside [`fluttersdk_artisan`](https://fluttersdk.com/artisan/mcp/setup). Setup is therefore the substrate's `.mcp.json` plus a one-line provider registration: install the substrate, register `DuskArtisanProvider`, and the 31 `dusk_*` tools surface automatically. ## Prerequisites Before wiring any client config: 1. The consumer's `pubspec.yaml` depends on `fluttersdk_artisan` and `fluttersdk_dusk`. 2. The consumer's `bin/artisan.dart` (the standard scaffold from `dart run fluttersdk_artisan install`) lists `DuskArtisanProvider` in its provider factory list, or relies on the auto-discovered `lib/app/_plugins.g.dart` barrel populated by `dart run fluttersdk_artisan plugins:refresh`. 3. `dart run fluttersdk_artisan list` shows the dusk commands (`dusk:snap`, `dusk:tap`, etc.). When they are missing, the provider is not registered. The MCP server stays online with zero apps running. Plugin tool calls lazy-reconnect to the VM Service URI recorded in `~/.artisan/state.json` on first call. ## Automated install (recommended) `fluttersdk_artisan` ships a built-in MCP installer that writes the canonical `.mcp.json` entry for you. Once dusk is in `pubspec.yaml` and the provider is registered, the same single command wires Claude Code, Cursor, VS Code, Windsurf, and any other client that reads `.mcp.json` at the project root: ```bash dart run fluttersdk_artisan mcp:install ``` The installer is idempotent: pre-existing entries are preserved and the `fluttersdk` key is replaced in-place on re-run. Override the target path per client: ```bash # VS Code (per-project) dart run fluttersdk_artisan mcp:install --path .vscode/mcp.json # Cursor (per-project) dart run fluttersdk_artisan mcp:install --path .cursor/mcp.json ``` To remove the entry later: ```bash dart run fluttersdk_artisan mcp:uninstall ``` ## Canonical `.mcp.json` entry When writing the file by hand (or wiring a client whose path is not yet covered by `mcp:install --path`): ```json { "mcpServers": { "fluttersdk": { "command": "dart", "args": ["run", "fluttersdk_artisan:mcp"], "cwd": "." } } } ``` The `cwd` field must point at the project root (the directory that contains the consumer's `pubspec.yaml`). The server binary is the substrate's `bin/mcp.dart`; the dusk descriptors ride on it. ## Per-client install | Client | Config path | After edit | |---|---|---| | Claude Code | `.mcp.json` (project) or `~/.claude.json` (user) | `/mcp reconnect fluttersdk` | | Cursor | `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (user) | Auto-reload | | VS Code (GitHub Copilot Workspace) | `.vscode/mcp.json` with `"servers"` key + `"type": "stdio"` | Reload window | | Continue | `.continue/config.json` `mcpServers` block | Restart Continue panel | | Windsurf | Windsurf MCP settings panel | Reload Cascade panel | | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) / `%APPDATA%\Claude\claude_desktop_config.json` (Windows) | Fully quit + relaunch (close-window != quit) | For Claude Code via CLI: ```bash claude mcp add fluttersdk -- dart run fluttersdk_artisan:mcp # or project-scoped: claude mcp add --scope project fluttersdk -- dart run fluttersdk_artisan:mcp ``` For the VS Code MCP shape (note the `"servers"` key, not `"mcpServers"`, plus the explicit transport type): ```json { "servers": { "fluttersdk": { "type": "stdio", "command": "dart", "args": ["run", "fluttersdk_artisan:mcp"], "cwd": "." } } } ``` ## Reconnect ritual Claude Code, Continue, and Windsurf do NOT auto-reconnect when `.mcp.json` or `.artisan/mcp.json` (the visibility filter) changes. After every edit: - **Claude Code:** run `/mcp reconnect fluttersdk` in the chat. The slash command re-initializes only the named server; other MCP entries stay connected. - **VS Code / Continue:** reload the editor window or restart the panel. - **Windsurf:** reload the Cascade panel. - **Cursor:** picks up changes on its own; no manual action needed. The substrate MCP server stays online during a reconnect; the client simply re-runs `initialize` and reads the refreshed tool catalog. ## Troubleshooting **The server is online but no app is running.** This is normal. The substrate MCP server starts without requiring `~/.artisan/state.json`. Every `dusk_*` tool call returns an actionable error (`"VM Service unreachable: state.json missing"`) until you run `dart run fluttersdk_artisan start`. Once the state file exists the next tool call lazy-reconnects. **`dusk_*` tools missing from the catalog.** The provider is not registered. Verify by running `dart run fluttersdk_artisan list` and confirming the `dusk:*` command block. If the block is empty, add `DuskArtisanProvider.new` to the consumer's `artisanProviders` list in `bin/artisan.dart`, or run `dart run fluttersdk_artisan plugins:refresh` to regenerate the auto-discovery barrel. **Lazy-reconnect on first `tools/call` is slow (~1s).** Expected; the substrate opens a WebSocket to the VM Service URI on demand. Subsequent calls reuse the cached connection. **Tool visibility filter.** Hide a tool surface without uninstalling: edit `.artisan/mcp.json` to add the tool name under `tools.deny`. Deny always wins over allow. Run the reconnect ritual after editing. ## Related - [overview.md](overview.md): tool catalog, dispatch surfaces (`ext.dusk.*` vs. `artisan:dusk:*`), lifecycle. - [tool-reference.md](tool-reference.md): per-tool input schema and example payloads. - [Substrate MCP setup](https://fluttersdk.com/artisan/mcp/setup): the full per-client install matrix for the underlying server.