Problem
mcp2cli schema <server>.<tool> and the --params help render the flat MCP inputSchema from tools/list. When a tool has a nested object parameter, the sub-fields are opaque — a CLI caller can't discover them.
Concrete case (Open Brain, contract 2026-06-19.memory-tools.v5, live at http://10.71.1.21:3100/mcp):
$ mcp2cli schema open-brain.append_session_event
"metadata": { "description": "Arbitrary JSON metadata; max 50 keys, max 100KB total" } # opaque
But OB's metadata now carries a recognized nested field, share_candidate (boolean), which nominates an event for promotion to the shared-kb namespace — with rich usage help. A CLI caller (Rico/Claude via mcp2cli) currently has no way to discover it from mcp2cli schema; they'd have to read the OB source. The flat tool list hides it.
This is the bridge half of the new OB memory-promotion feature (open-brain #161/#172). The agents (rtech-hermes) consume OB directly over HTTP, but mcp2cli is the path Rico/Claude use, and right now that path can't see or correctly form a share_candidate nomination.
Repro
mcp2cli open-brain --help # append_session_event + promote_shared present (good — live discovery works)
mcp2cli schema open-brain.append_session_event # metadata shown as opaque; no share_candidate sub-field
Proposed approaches (maintainer's call)
A. Recurse nested object fields (source-agnostic). When an inputSchema property is type: object with nested properties (standard JSON Schema) — or OB's contract dialect fields — render the sub-fields with their description/type/required. Works for any MCP server, not just OB. This is the minimal, general fix.
B. Prefer get_contract for servers that publish it (OB-aware). OB exposes get_contract with a richer per-field/per-tool help manifest (tool_contracts.append_session_event.input_schema.metadata.fields.share_candidate.description, etc.). mcp2cli could, for servers advertising that capability, render schema/help from the contract instead of the flat tools/list. Richest help, but couples mcp2cli to the OB contract dialect (fields vs properties).
A handles the general case; B gives the best help for OB specifically. They're not exclusive — A could read fields OR properties, getting most of B's benefit generically.
Acceptance
mcp2cli schema open-brain.append_session_event shows metadata.share_candidate (boolean) with its help text.
- A
--params '{"...","metadata":{"share_candidate":true}}' call round-trips correctly (already works at the transport layer; this is purely the discoverability/help gap).
- No regression for flat tools (e.g.
promote_shared renders unchanged — verified it already shows table/id/reason/dry_run correctly).
Context
- Open Brain server source of truth: contract
tool_contracts in open-brain repo src/contract-schemas.ts; nested help lives under metadata.fields.
- Live verification done 2026-06-19:
promote_shared and append_session_event ARE discovered live (no static cache to update) — the only gap is nested-field rendering.
Problem
mcp2cli schema <server>.<tool>and the--paramshelp render the flat MCPinputSchemafromtools/list. When a tool has a nested object parameter, the sub-fields are opaque — a CLI caller can't discover them.Concrete case (Open Brain, contract
2026-06-19.memory-tools.v5, live athttp://10.71.1.21:3100/mcp):But OB's
metadatanow carries a recognized nested field,share_candidate(boolean), which nominates an event for promotion to the shared-kb namespace — with rich usage help. A CLI caller (Rico/Claude via mcp2cli) currently has no way to discover it frommcp2cli schema; they'd have to read the OB source. The flat tool list hides it.This is the bridge half of the new OB memory-promotion feature (open-brain #161/#172). The agents (rtech-hermes) consume OB directly over HTTP, but mcp2cli is the path Rico/Claude use, and right now that path can't see or correctly form a
share_candidatenomination.Repro
Proposed approaches (maintainer's call)
A. Recurse nested object fields (source-agnostic). When an
inputSchemaproperty istype: objectwith nestedproperties(standard JSON Schema) — or OB's contract dialectfields— render the sub-fields with theirdescription/type/required. Works for any MCP server, not just OB. This is the minimal, general fix.B. Prefer
get_contractfor servers that publish it (OB-aware). OB exposesget_contractwith a richer per-field/per-tool help manifest (tool_contracts.append_session_event.input_schema.metadata.fields.share_candidate.description, etc.). mcp2cli could, for servers advertising that capability, render schema/help from the contract instead of the flattools/list. Richest help, but couples mcp2cli to the OB contract dialect (fieldsvsproperties).A handles the general case; B gives the best help for OB specifically. They're not exclusive — A could read
fieldsORproperties, getting most of B's benefit generically.Acceptance
mcp2cli schema open-brain.append_session_eventshowsmetadata.share_candidate(boolean) with its help text.--params '{"...","metadata":{"share_candidate":true}}'call round-trips correctly (already works at the transport layer; this is purely the discoverability/help gap).promote_sharedrenders unchanged — verified it already shows table/id/reason/dry_run correctly).Context
tool_contractsinopen-brainreposrc/contract-schemas.ts; nested help lives undermetadata.fields.promote_sharedandappend_session_eventARE discovered live (no static cache to update) — the only gap is nested-field rendering.