Skip to content

mcp

mytool mcp [serve [--transport stdio|sse|http] [--bind ADDR] | list]

Feature: Mcp, registered by the rtb-mcp crate. Passthrough subtree. No subcommand means serve over stdio.

mcp rejects --output. Its inner parser does not strip the global flag, so mytool mcp list --output json fails with unexpected argument '--output'. mcp list already emits JSON.

mcp serve

Runs the Model Context Protocol server in the foreground until the transport closes or App::shutdown fires.

Flag Default Meaning
--transport <T> stdio stdio, sse or http
--bind <ADDR> none Socket address. Required for sse and http, ignored for stdio

--transport sse or http without --bind fails immediately with `mcp serve --transport sse` requires `--bind ADDR` — the message names the transport you asked for, so http gets `mcp serve --transport http` requires `--bind ADDR`.

Only stdio is implemented

Transport Status
stdio Shipped. What MCP clients that spawn a server as a subprocess expect
sse Accepted by the parser, then fails with an McpError::Transport
http Accepted by the parser, then fails with an McpError::Transport

Supplying --bind for those two gets you past argument validation and no further. Streamable-HTTP wiring is listed as future work in the crate; there is no configuration that makes it work in this release.

mcp list

Prints one JSON object per line — a JSON Lines stream, not a JSON array — for every command whose Command::mcp_exposed() returns true.

{"name":"deploy","description":"Deploy the thing","input_schema":{"type":"object"}}
Key Source
name CommandSpec::name
description CommandSpec::about
input_schema Command::mcp_input_schema(), or {"type":"object"} when None

list walks BUILTIN_COMMANDS directly and does not consult the runtime Features set. A command whose feature is disabled — so it does not appear in --help — is still listed here if it opts into MCP exposure.

Both defaults are false / None, so a tool that has not opted anything in prints nothing at all and exits 0.

What a tools/call runs

Each exposed command becomes one MCP tool. A tools/call builds a fresh instance from the command's registry factory and runs Command::run against a clone of the host App — the same code path the CLI dispatches, in the same process. A tool can be addressed by its CommandSpec::name or by any of its aliases.

Three constraints worth knowing before exposing a command:

  • Arguments are not delivered. The input_schema is published to clients, and the arguments a client sends are then discarded: call_tool reads the tool name and nothing else. Command::run receives an App whose trailing_args() is empty. Only commands that need no input do anything useful over MCP today.
  • The reply is a fixed string, not the command's output. A successful call returns the text <name> ok; a failing one returns <name>: <error> with is_error set. Whatever the command printed went to the process's stdout — which, under the stdio transport, is the protocol stream itself. A command that prints will corrupt the session.
  • Failures do not stop the server. A command error is reported as that call's error result and the service loop continues.

Failure modes

Variant Cause
McpError::Transport(String) Bind, accept or I/O failure — including the sse/http stubs
McpError::Protocol(String) No registered tool with the requested name, via McpServer::dispatch
McpError::Command { command, message } Command::run returned an error, via McpServer::dispatch

McpServer::dispatch is the library-side entry point for the same dispatch logic and is what surfaces those last two variants. Over the wire, an unknown tool name becomes an rmcp invalid_params error and a command failure becomes an error result on the call.