Summary
An mcp-client step type that spawns a CLI process acting as an MCP client, passes a structured tool call as arguments, and ingests the JSON response into the routine report.
Motivation
Many services expose functionality through an MCP server fronted by a CLI wrapper (e.g. mytool mcp, mytool briefing --json). The existing harness step type can spawn the process, but it treats stdout as opaque text. An mcp-client step would understand the MCP tool-call/response envelope, validate the schema, and promote the result into the report's data field as a first-class structured payload.
This enables any MCP-capable CLI to participate in a routine without writing a custom step type — the step type is the adapter.
Proposed design
Step type: mcp-client
Config shape:
[[routines.morning.steps]]
name = "briefing"
type = "mcp-client"
command = "mytool"
args = ["briefing", "--json"] # CLI args that cause the tool to emit MCP JSON
tool = "briefing_get" # optional: MCP tool name to call
params = { hours = 24 } # optional: tool input params
timeout = 60
env = { MY_TOKEN = { file = "~/.keys/mytoken" } }
Two invocation modes:
- Subprocess JSON mode (
args only): spawn command, capture stdout, parse as MCP CallToolResult. Simple; works with any CLI that emits a valid MCP response body.
- stdio MCP mode (
tool + params): start the process as a stdio MCP server, send a tools/call request over stdin, read the response, shut down. Full protocol; works with any modulex-mcp-compatible server.
Data contract:
The data field carries the raw content array from the MCP CallToolResult, schema-tagged mcp-client/1.
Behavior:
- Non-zero exit or malformed JSON:
success = false, error set — routine continues (soft failure).
isError: true in the MCP response propagates as success = false.
- Spawned only through
ExecGate; command must be in the declared or leash-granted program list.
Alternatives considered
harness step: works today for text output; lacks structured data promotion and MCP envelope awareness.
- Writing a custom Rust step per service: correct but defeats the purpose of a generic adapter.
Acceptance criteria
Summary
An
mcp-clientstep type that spawns a CLI process acting as an MCP client, passes a structured tool call as arguments, and ingests the JSON response into the routine report.Motivation
Many services expose functionality through an MCP server fronted by a CLI wrapper (e.g.
mytool mcp,mytool briefing --json). The existingharnessstep type can spawn the process, but it treats stdout as opaque text. Anmcp-clientstep would understand the MCP tool-call/response envelope, validate the schema, and promote the result into the report'sdatafield as a first-class structured payload.This enables any MCP-capable CLI to participate in a routine without writing a custom step type — the step type is the adapter.
Proposed design
Step type:
mcp-clientConfig shape:
Two invocation modes:
argsonly): spawn command, capture stdout, parse as MCPCallToolResult. Simple; works with any CLI that emits a valid MCP response body.tool+params): start the process as a stdio MCP server, send atools/callrequest over stdin, read the response, shut down. Full protocol; works with anymodulex-mcp-compatible server.Data contract:
The
datafield carries the rawcontentarray from the MCPCallToolResult, schema-taggedmcp-client/1.Behavior:
success = false,errorset — routine continues (soft failure).isError: truein the MCP response propagates assuccess = false.ExecGate; command must be in the declared or leash-granted program list.Alternatives considered
harnessstep: works today for text output; lacks structured data promotion and MCP envelope awareness.Acceptance criteria
mcp-clientstep type inmodulex-coredataschema pinned with golden file testisErrorpropagationExecGatemodulex doctorreports whether the command is available