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
wheelscommands 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.
How it works
Section titled “How it works”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.
wheels new writes the configuration for you: a new app’s root has .mcp.json (Claude Code) and .opencode.json (OpenCode), unless you created it with --no-agents. For an existing app, run this from its root:
wheels setup agentsIt writes the same two files, merging the wheels entry into any servers they already list. (The command is setup agents, not setup mcp: LuCLI intercepts the token mcp in any argument position.)
To write it by hand, 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:
{ "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.
Verifying the server responds
Section titled “Verifying the server responds”Before wiring it into an IDE, you can confirm the server starts and enumerates tools with the built-in --once helper:
wheels mcp wheels --once tools/listThat 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.
Tools exposed
Section titled “Tools exposed”Every public function in the Wheels Module is auto-discovered as an MCP tool. Names in tools/list are the bare function names — 17 tools (4.1.x has no lookup, 4.1.2 and earlier also list create, and 4.1.0 and earlier deploy; see below):
| Tool | Purpose |
|---|---|
generate | Scaffold a model, controller, view, migration, scaffold, route, test, property, or helper. |
destroy | Remove 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. |
migrate | Run, roll back, or inspect database migrations. |
seed | Run convention-based seeds against the configured environment. |
db | Database utility operations: reset (migrate, then reseed), status, and version. |
test | Run the app or core test suite and return results. |
reload | Reload the app via the running dev server. |
routes | List registered routes. |
info | Print project, framework, and environment info. |
analyze | Run the codebase analyzer (conventions, anti-patterns, drift). |
validate | Run configuration and schema validation checks. |
doctor | Diagnose install, project, and runtime issues. |
stats | Count models, controllers, routes, tests, migrations. |
notes | Surface TODO, FIXME, HACK, OPTIMIZE annotations from the codebase. |
lookup | Look up the Wheels API reference and the guides offline: a function name returns its full entry (parameters, example, link), a phrase returns the best-matching guide sections and functions. |
upgrade | Scan the project for breaking changes (check, read-only) or swap vendor/wheels/ to a newer release (apply, writes with a backup). |
packages | Search, show, add, update, and remove Wheels packages; manage the registry cache. |
Tools deliberately hidden
Section titled “Tools deliberately hidden”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.create—create appforwards tonew, so it is hidden for the same reason. For the same reasongeneratedoes not advertiseappas atypeover MCP. Both stay available in a terminal. (4.1.2 and earlier listcreateas a tool.)browser— multi-step browser testing flow with its own subcommand tree.coverage— instrumentsapp/on disk, then runs the suite; stateful rather than a single call.engines— manages the RustCFML server backend, a dev-server lifecycle command likestart/stop.framework—framework installwrites the framework intovendor/wheels/, a side-effecting install.setup(and its deprecated forwardermap) — writes the agent configuration files described above.docs—docs fetchdownloads the offline documentation bundle.dbmigrate— alias formigrate, excluded to avoid a duplicate tool entry.onMissingMethod— the unknown-command handler; a CFML hook, not a command.jobs—jobs workis a long-lived worker poll loop with no single-call MCP semantics.deploy— Kamal-style production deploys. It reaches remote hosts over SSH, pushes images, and restarts containers, so its side effects land outside your machine. Run it from a terminal. (4.1.0 and earlier still list it as a tool.)mcpToolSpecs— the per-tool inputSchema registry LuCLI reads; not itself a tool.mcp— the meta command itself; exposing it would let an agent recursively launch MCP servers.d— short alias fordestroy, excluded to avoid a duplicate tool entry (the canonicaldestroyis exposed).g— short alias forgenerate, excluded for the same duplicate-entry reason asd.main— the barewheelsno-args dispatch target; it is not a subcommand.- Any function whose name begins with
$— internal helpers keptpubliconly so unit tests can reach them (a CFML testing carve-out).mcpHiddenTools()discovers these structurally viagetMetaData(this), so a future$helperadded 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.
Troubleshooting
Section titled “Troubleshooting”The server never responds / the IDE shows zero tools. The most common cause: GUI-launched editors (VS Code, Cursor, Claude Desktop opened from the dock or Start menu) don’t inherit your shell’s PATH, so the bare "command": "wheels" in .mcp.json can’t be found — and most clients fail silently. Fix it by using the absolute binary path:
{"mcpServers": {"wheels": {"command": "/opt/homebrew/bin/wheels", "args": ["mcp", "wheels"]}}}(which wheels in a terminal prints the path to use — e.g. /usr/bin/wheels on apt/yum installs, %USERPROFILE%\scoop\shims\wheels.exe on Scoop.) Launching the editor from a terminal (code .) also works, since the child inherits the shell environment.
Tools appear but calls fail. Run wheels mcp wheels by hand in a terminal at your project root — startup errors that the IDE swallows print directly there.
Deprecated HTTP endpoint
Section titled “Deprecated HTTP endpoint”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.