Skip to content

Command Line Tools

MCP Integration

The wheels binary can run as a Model Context Protocol (MCP) server over stdio, letting an AI IDE invoke subcommands — generate, migrate, test, routes, and so on — as structured tool calls instead of shell strings. The AI gets a typed tool catalog; you skip the quoting and parsing that trips up shell-based automation.

You’ll use this for:

  • Letting Claude Code, Cursor, or another MCP-aware IDE run wheels commands directly, with arguments marshalled as JSON rather than parsed out of chat.
  • Avoiding shell-escaping bugs when an agent wants to pass attribute lists (title:string, body:text) or path arguments.
  • Automating routine work — generating scaffolds, running migrations, seeding databases — from an editor session without copy-pasting commands.

LuCLI ships a generic mcp subcommand that wraps any installed module’s public functions as MCP tools over stdio JSON-RPC. Running wheels mcp wheels starts that server bound to the Wheels Module — every public function in cli/lucli/Module.cfc becomes a tool named after the function itself (for example, generate, migrate). Tool names appear unprefixed in tools/list; the wheels server entry in your MCP config is what namespaces them per client. The AI IDE spawns wheels as a subprocess, speaks newline-delimited JSON-RPC over stdin/stdout, and receives tool results the same way. No network listener is involved.

Add an .mcp.json file to your project root (or wherever your IDE expects it). Most AI IDEs auto-load this file when the project opens:

.mcp.json
{
"mcpServers": {
"wheels": {
"command": "wheels",
"args": ["mcp", "wheels"]
}
}
}

That’s the whole configuration. The first wheels is the binary name; the second is the module name to expose. The IDE launches the subprocess on demand — you don’t need to keep wheels mcp wheels running yourself, and the server exits when the IDE disconnects.

Don’t try wheels mcp on its own to see this snippet: on the released launcher, LuCLI reserves the mcp verb and a bare invocation exits with mcp: missing module name instead of reaching the Wheels Module’s help text. To check the server from a shell, use the --once smoke test below. There is no setup wizard and no generated file — add the .mcp.json snippet manually.

Before wiring it into an IDE, you can confirm the server starts and enumerates tools with the built-in --once helper:

smoke-test — run in your project root
wheels mcp wheels --once tools/list

That runs a single MCP method and exits — useful for smoke-testing without opening a long-lived stdio session. The output is a JSON-RPC response listing every exposed tool with its input schema.

Every public function in the Wheels Module is auto-discovered as an MCP tool. Names in tools/list are the bare function names — 18 tools on a 4.0.3 install:

ToolPurpose
generateScaffold a model, controller, view, migration, scaffold, route, test, property, or helper.
destroyRemove a previously generated component. The default resource type cascades (model + controller + views + tests + route + drop-table migration); model, controller, and view are scoped to that artefact only.
migrateRun, roll back, or inspect database migrations.
seedRun convention-based seeds against the configured environment.
dbDatabase utility operations (schema, reset, status).
testRun the app or core test suite and return results.
reloadReload the app via the running dev server.
routesList registered routes.
infoPrint project, framework, and environment info.
analyzeRun the codebase analyzer (conventions, anti-patterns, drift).
validateRun configuration and schema validation checks.
doctorDiagnose install, project, and runtime issues.
statsCount models, controllers, routes, tests, migrations.
notesSurface TODO, FIXME, HACK, OPTIMIZE annotations from the codebase.
createCreate an application (currently only wheels create app <name>; forwards to wheels new).
upgradeScan the project for breaking changes against a target framework version (read-only).
deployKamal-style production deploys (full deploy, rollback, config, setup, bootstrap, exec).
packagesSearch, show, add, update, and remove Wheels packages; manage the registry cache.

A handful of public CLI commands are excluded from MCP discovery via mcpHiddenTools() in Module.cfc. They stay reachable from the terminal but never appear in an MCP tools/list:

  • start, stop — dev server lifecycle. Stateful, long-lived processes don’t fit the single-call MCP model.
  • console — interactive CFML REPL. Requires a live stdin/stdout loop, which the MCP transport owns.
  • new — scaffolds an entire new project. Destructive and requires interactive prompts for project context.
  • browser — multi-step browser testing flow with its own subcommand tree.
  • mcp — the meta command itself; exposing it would let an agent recursively launch MCP servers.
  • d — short alias for destroy, excluded to avoid a duplicate tool entry (the canonical destroy is exposed).
  • g — short alias for generate, excluded for the same duplicate-entry reason as d.
  • main — the bare wheels no-args dispatch target; it is not a subcommand.
  • Any function whose name begins with $ — internal helpers kept public only so unit tests can reach them (a CFML testing carve-out). mcpHiddenTools() discovers these structurally via getMetaData(this), so a future $helper added to the module cannot accidentally surface as a callable MCP tool without a manual denylist update.

If you need one of these behaviours from an AI IDE, invoke it via a shell tool — don’t try to expose it as an MCP tool.

Earlier versions of the framework shipped an in-dev-server MCP endpoint at /wheels/mcp, implemented as a CFML view that spoke Streamable HTTP JSON-RPC. That endpoint is deprecated as of Wheels 4.0. It still responds for backwards compatibility, but it emits a one-time warning to the wheels_mcp log on first use per JVM and will be removed in a future release.

Migrate to the stdio surface by switching your IDE’s MCP server definition to the .mcp.json shown above. The stdio server covers the same tool set, does not require a running dev server for file-based operations (generate, migrate, stats, and so on), and is the only surface that will be maintained going forward.