mcp:serve
Start the fluttersdk MCP server over stdio JSON-RPC, exposing substrate and plugin-contributed tools to AI clients such as Claude Code, Cursor, and Windsurf.
Contents
Basic Usage
dart run fluttersdk_artisan mcp:serve
The server opens a stdio JSON-RPC channel, registers every tool that passes the
active filter, and blocks until the MCP client disconnects. Exit code is 0 on a
clean disconnect, 1 on a startup StateError.
In normal usage the AI client launches the server automatically from your .mcp.json
entry. The standalone form above is useful for debugging the tool list before wiring.
Synopsis
dart run fluttersdk_artisan mcp:serve
[--include-package ]...
[--exclude-package ]...
[--include-tool ]...
[--exclude-tool ]...
All four flags are repeatable. Each can also be set via environment variable or
.artisan/mcp.json (see 3-Layer Filter).
| Flag | Effect |
|---|---|
--include-package |
Accept only tools from the named package. CLI value replaces env and file allow lists for the package axis. |
--exclude-package |
Block all tools from the named package. Deny wins over allow across every layer. |
--include-tool |
Accept only the named tool. CLI value replaces env and file allow lists for the tool axis. |
--exclude-tool |
Block the named tool. Deny wins over allow across every layer. |
Soft-Fail Behavior
The server does not require a running Flutter app at startup. When
~/.artisan/state.json is absent or contains no vmServiceUri, initialization
completes normally: all tools register and the server stays online
(source: mcp_server.dart:137-149).
Tool calls that need the VM Service attempt a lazy reconnect on first
invocation (source: mcp_server.dart:228-256):
- Dispatch checks whether
_vmClientis null. - If null, a single shared in-flight future reads
~/.artisan/state.json, connects the WebSocket, and captures the main isolate ID. - Concurrent calls that arrive during the reconnect await the same future, preventing a client-leak race.
- On failure, dispatch returns
isError: truewith an actionable message:Run artisan start to launch the Flutter app, then retry the tool call. - The guard clears in
finallyso the next call retries cleanly.
Note: the server does NOT auto-reload filter configuration in V1. After editing
.artisan/mcp.json or any ARTISAN_MCP_* env var, run /mcp reconnect fluttersdk
in Claude Code (or restart the server process in other clients) to apply the change.
3-Layer Filter
Tool visibility is controlled by three layers using Cargo-style precedence
(source: mcp_filter_config.dart:97-235):
| Layer | Source | Priority |
|---|---|---|
| File | .artisan/mcp.json in project root |
Lowest |
| Env | ARTISAN_MCP_* environment variables |
Middle |
| CLI | --include-* / --exclude-* flags |
Highest |
Allow lists (replace): a non-null value at a higher layer replaces the lower
layer entirely for that axis. Resolution: cli.allow ?? env.allow ?? file.allow.
Null at all three layers means "include all".
Deny lists (union): the union of all three layers. A name denied at any layer is denied in the result; deny always wins over allow.
File layer
{
"packages": { "allow": null, "deny": ["fluttersdk_telescope"] },
"tools": { "allow": ["artisan_start", "artisan_tinker"], "deny": [] }
}
An absent file is treated as "no opinion" (all tools pass).
Env layer
| Variable | Axis |
|---|---|
ARTISAN_MCP_PACKAGES_ALLOW |
Package allow list (CSV) |
ARTISAN_MCP_PACKAGES_DENY |
Package deny list (CSV) |
ARTISAN_MCP_TOOLS_ALLOW |
Tool allow list (CSV) |
ARTISAN_MCP_TOOLS_DENY |
Tool deny list (CSV) |
CLI layer
Pass each --include-* / --exclude-* flag multiple times to accumulate entries.
A non-empty --include-* replaces the env and file allow list for that axis.
Tools Surfaced
At initialize time the server merges two tool sets, then applies the active filter.
Substrate tools (10): run in-process via the artisan command registry. Nine work
without a running Flutter app; artisan_tinker dispatches over the VM Service and
lazy-reconnects on first call. Their filter package name is fluttersdk_artisan.
| MCP Tool Name | Artisan Command |
|---|---|
artisan_start |
start |
artisan_stop |
stop |
artisan_status |
status |
artisan_logs |
logs |
artisan_restart |
restart |
artisan_reload |
reload |
artisan_hot_restart |
hot-restart |
artisan_doctor |
doctor |
artisan_list |
list |
artisan_tinker |
tinker |
Excluded from the substrate allowlist: help, make:*, *:refresh, mcp:*,
plugin:*, consumer:scaffold. These require a TTY, mutate source on disk, or
recurse into the server itself (source: mcp_server.dart:744-755).
Plugin tools: contributed via ArtisanServiceProvider.mcpTools() on each
registered provider. The default returns an empty list. Providers such as
DuskArtisanProvider and TelescopeArtisanProvider override it to expose tools that
dispatch over the VM Service extension surface and require a running Flutter app. Both
sets flow through the same filter, so a --exclude-tool deny against a plugin tool name
behaves identically to a deny against a substrate name. The current plugin tool catalogs
live on each plugin's own MCP tool reference site
(fluttersdk_dusk,
fluttersdk_telescope).
Examples
1. Filter via file: allow only specific packages
{
"packages": { "allow": ["fluttersdk_artisan", "fluttersdk_dusk"], "deny": [] },
"tools": { "allow": null, "deny": [] }
}
dart run fluttersdk_artisan mcp:serve
Only substrate and Dusk tools register. Telescope is excluded because its package is not in the allow list.
2. Filter via env vars: deny specific tools
export ARTISAN_MCP_PACKAGES_DENY="fluttersdk_telescope"
dart run fluttersdk_artisan mcp:serve
All Telescope tools are excluded; all others remain available. The env deny is
UNIONed with any deny entries already in .artisan/mcp.json.
3. Filter via CLI flags: pin to a minimal tool set
dart run fluttersdk_artisan mcp:serve \
--include-tool artisan_start \
--include-tool artisan_stop \
--include-tool artisan_tinker
Only the three named tools register. Any tools.allow in .artisan/mcp.json or
ARTISAN_MCP_TOOLS_ALLOW is ignored for this invocation (CLI replaces).
Related
- mcp:install: write or update the
.mcp.jsonclient entry. - mcp:uninstall: remove the
fluttersdkentry from.mcp.json. - MCP setup guide: end-to-end wiring for Claude Code, Cursor, Windsurf.
- MCP tool reference: full parameter and return value reference for every substrate and plugin tool.