mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-12 05:49:00 +00:00
2e4a815d0c
* feat(mcp): cmdhelp-derived tool registry + shell-out dispatch (TASK-945)
The strategic centerpiece of PLAN-942: walk the cmdhelp Document built
from `pad`'s cobra tree and register every leaf as an MCP tool, with
shell-out dispatch back to the running binary. New pad commands (or
new flags) extend the MCP surface for free — no hand-mapping ~73
commands.
- internal/mcp/registry.go — Register() walks cmdhelp.Document, picks
leaves, applies a curated DefaultExcludes (db ops, auth, init,
agent install/update, server lifecycle, completion, edit, watch,
workspace lifecycle), builds an MCP Tool per leaf with input schema
derived from cmdhelp Arg/Flag types. Snake-case names: "item create"
→ "item_create".
- internal/mcp/dispatch.go — ExecDispatcher shells out to the pad
binary; BuildCLIArgs is a pure function that translates the JSON
args into a CLI invocation (positionals → flags → workspace
injection → --format json default). JSON stdout is surfaced as
StructuredContent for rich client rendering.
- internal/mcp/workspace.go — WorkspaceState (RWMutex-protected) +
pad_set_workspace built-in tool. Empty string clears the session
default; missing arg returns IsError without mutating state.
- cmd/pad/mcp.go — wire registry into `pad mcp serve` startup; build
the cmdhelp Document from cmd.Root(), resolve the running binary
via os.Executable, seed workspace from --workspace flag.
- 23 new unit tests across registry / dispatch / workspace files
(race-detector clean) covering: leaf identification, exclusion
prefix suppression, snake-case naming, pure CLI arg translation
(positionals + bool presence form + repeatable args & flags +
workspace/format injection), exec dispatcher (binary missing,
stdout capture, non-zero exit), workspace state mutation, and
end-to-end pad_set_workspace handler contract.
Live smoke (real binary, real stdio):
- tools/list returns 66 tools — pad_set_workspace + item_create
present, db_backup + mcp_serve correctly excluded.
- tools/call pad_set_workspace updates session state, then
auth_whoami shells out and returns structured JSON.
Parent: PLAN-942.
* fix(mcp): forward --url root flag + drop unwired --stdin (Codex round 1)
Two findings from Codex review of #335:
P1: --url root persistent flag was not forwarded to dispatched
subprocesses. If an MCP client launches `pad --url X mcp serve`,
every tool call ran against the default URL instead of X. Fixed by
adding RootFlags map[string]string to RegistryOptions; cmd/pad/mcp.go
captures urlFlag at startup and threads it through. BuildCLIArgs
now also takes a rootFlags map and injects each entry when not in
input (empty values skipped, agent value wins on collision).
P2: MCP tool schemas exposed `--stdin` flags but ExecDispatcher
never piped the agent's stdin to the subprocess. Calling e.g.
`item_create {stdin: true}` would block on EOF and create empty
content. The `--content` flag covers the same semantic via JSON
args, which IS wired. Hide stdin from the MCP surface (buildTool
filters out flagsHiddenFromMCP) AND drop it defensively in
BuildCLIArgs in case an agent's stale schema cache passes it.
Tests added (4 new + 2 updated):
- BuildCLIArgs: stdin dropped defensively, root flags injected,
empty root flag skipped, agent value wins over root flag.
- buildTool: omits stdin from input schema.
- Dispatch handler: forwards root flags through to CLI args.
Existing TestBuildCLIArgs_BoolPresenceForm rewritten to use
`dry-run` flag (since stdin is now filtered).
Live verified: `pad mcp serve` tools/list shows item_create with
content+10 other flags, no stdin. Round-trip preserved.
Parent: PLAN-942.