Files
pad/cmd
xarmian 342a564113 feat(mcp): read-only resource templates (TASK-946) (#336)
* feat(mcp): read-only resource templates for items / dashboard / collections (TASK-946)

Four MCP resource templates expose pad workspace state to agents
without requiring a tool invocation:

  pad://workspace/{ws}/items/{ref}  → single item markdown
  pad://workspace/{ws}/items        → list of items (JSON)
  pad://workspace/{ws}/dashboard    → project dashboard (JSON)
  pad://workspace/{ws}/collections  → collections + schemas (JSON)

Why resources, not tools: agents can `resources/read` a URI and
ingest the body directly into context without going through a
tool-call round-trip. Useful for "load TASK-5 then plan" workflows
where the agent shouldn't need to pick a tool.

Implementation:
- internal/mcp/resources.go (new) — RegisterResources installs all
  four templates on an MCPServer; ResourceFetcher interface +
  ExecResourceFetcher shell-out (separate from Dispatcher because
  resource handlers return raw bytes, not CallToolResult).
- parsePadURI extracts (workspace, kind, arg) from pad:// URIs;
  defensive guards reject mismatched URIs at each handler.
- rootFlagsToArgs forwards startup --url to every fetched call
  (same contract as TASK-945's tool dispatch).
- cmd/pad/mcp.go wires RegisterResources after the tool registry
  in mcpServeCmd.

15 new unit tests:
- parsePadURI: all 4 forms + 4 malformed inputs
- each handler: dispatches correct CLI args + MIME type
- readItem rejects mismatched URI (defensive)
- fetch errors propagate as Go errors (so MCP returns JSON-RPC
  error rather than empty contents)
- root flag forwarding via the resources path
- ExecResourceFetcher: missing binary, stdout capture, non-zero
  exit folds stderr into error

Live verified:
- resources/templates/list returns 4 templates with correct mime
  types and uri patterns.
- resources/read pad://workspace/docapp/items/TASK-944 returns
  1764 bytes of markdown.

Parent: PLAN-942.

* fix(mcp): compose full item markdown from JSON in resource path (Codex round 1)

Codex flagged: pad://workspace/{ws}/items/{ref} fetched
`pad item show --format markdown` which prints only item.Content
(see cmd/pad/main.go:2562). The resource description promised
"Full markdown content … includes title, fields, body, and links",
so clients reading the URI lost ref/title/metadata/parent and
couldn't reliably identify the item.

Fix scoped to the resource path (rather than changing the CLI's
markdown output, which other callers may parse): readItem fetches
`--format json` and a new formatItemAsMarkdown composes the
document — heading with ref + title, optional parent link, sorted
metadata fields, then the content body.

3 new unit tests + the existing readItem test rewritten:
- Full-shape JSON → exact markdown layout (deterministic via sorted keys)
- Missing fields → heading-only doc, no panic
- Empty `{}` fields → no stray list section
- Invalid JSON → error propagates

Live verified: pad://workspace/docapp/items/TASK-944 now returns
"# TASK-944: <title>\n\n**Parent:** PLAN-942 — ...\n\n- **priority:**
high\n- **status:** done\n\n<body>" — full identification + traversable
parent link, body intact.

Parent: PLAN-942.
2026-05-01 08:54:02 -04:00
..