At a glance
| Code | WI-016 |
| Phase | Platform & Contracts |
| Order | 16 of 93 |
| Story points | 8 |
| Primary surface | packages/mcp-server (hardened governed surface, stdio) |
| Retires | — |
| Depends on | Source ingestion + promotion CORE contract (one-door flow, promoteInventoryCandidate, idempotency, layered dedup, provenance, plugin-event audit, permission matrix) |
| Blocks | MCP proposal/approval & controlled actions (proposal+grant+automation-policy, policy evaluator, domain-mapped actions, bulk-as-frozen-plan, live e2e) |
- Evidence
- docs/ARCHITECTURE.md; docs/technical/mcp-tools.md
Goals
Expose safe MCP tools first and gate the dangerous ones; no tool bypasses the ingestion contract or touches credentials (mcp-tools.md).
Implementation — what to build
Spec (docs/specs/P7)
- MCP is a governed interface, not a second writer; read/candidate tools are lower-risk but still auth/scope/validate/idempotent/audit; mock != permissive.
- Read/candidate tools project permission-aware views FROM the canonical stored ScanResult/candidates (result.payload.candidates[...]); tools must not re-flatten, fork, or invent a parallel result shape. One canonical shape end-to-end (P1->P2->P3->P6->MCP).
Build (governed surface)
- mcp_clients registration + trust; server-resolved tool_context (client tenant/actor hints verified, not trusted); tool registry + versioned schemas + risk + filtered discovery; public + scoped read tools (permission-aware projections, no base-table rows); candidate/draft tools via P5 (create_candidate, csv preview/apply, attach photo, draft copy, stage export); idempotency store; response/error envelopes; mock/live; plugin_events audit; rate limits; credential redaction; prompt-injection inert-data handling.
Test (no live host)
- Discovery filtering by role; auth/tenant scope (client can't override); candidate->P5 chain (no canonical item); current-tool compatibility; mock nonpersistence; credential isolation; prompt-injection inert; idempotent replay; plugin-event completeness.
Gap-resolution expansion (D26, 2026-06-20)
- MCP current-tool hardening: live mode resolves actor/tenant, routes through the P5 candidate chain, enforces idempotency, drops service-role/anon broad access — keeping current tool names (closes C25).
Checklist
- ○ Read tier (safe): list_sales, get_sale, list_items, search_marketplace, get_demand_signals, list_import_runs.
- ○ Candidate tier (safe): create_inventory_candidate, run_manual_import, map_csv_columns, draft_listing_copy, stage_export.
- ○ Approval-gated: promote_candidate, publish_sale, update_item_status, notify_matched_buyers (per-action approval or auditable policy).
- ○ Wrap existing src/lib/troveSnapIngestion.ts functions; never write canonical tables directly.
- ○ Every call logs plugin_events; no tool reads credential_refs contents.
Gates & testing
- ○ P7 MCP tool surface exposes read/search/candidate tools first, with approval gates on publish/bulk/delete tools, wrapping existing ingestion functions.
CODE TEST HITL QA
Requirements
REQ-PLAT-003 accepted The MCP tool surface must expose safe tools first and gate dangerous ones. Done when: Read/search/candidate tools land first; publish/bulk/delete tools require explicit approval or an auditable, revocable automation policy.
REQ-MCP-001 implemented A read-only MCP tool tier must be available (list/get sales, list items, search marketplace, demand signals, import runs). Done when: A stdio MCP server exposes the read tools; without env it serves mock data; with env it reads live.
REQ-MCP-002 implemented A candidate-writing MCP tier must create candidates/imports/events only (create_candidate, run_manual_import, map_csv_columns, draft_listing_copy, stage_export). Done when: These tools write source_import_records / inventory_candidates / plugin_events; nothing canonical; every call logs plugin_events.
REQ-MCP-003 accepted Approval-gated MCP tools (promote_candidate, publish_sale, update_item_status, notify_matched_buyers) must require explicit seller approval or an auditable, revocable automation policy. Done when: No tool bypasses promoteInventoryCandidate(); none touch credential_refs contents; live publishing/paid/destructive actions are never auto-approved by default.
Verify (done when)
The existing stdio server is hardened: client registration + server-resolved actor/tenant context; tool registry + versioned I/O schemas + risk metadata + filtered discovery; public (public-safe) + scoped read tools with permission-aware projections; candidate/draft tools that write only through the P5 one-door (run/record/candidate/plugin event, never canonical inventory); idempotency; stable response/error envelopes; mock/live (mock never persists, can't be upgraded via a tool arg); plugin-event audit; rate limits; credential isolation; prompt-injection safety; current five tools still work. Per spec section 43/44 (read/candidate rows). Section 46 reconciliations tracked.
Cost triggers
No paid API / infra spend triggered by this item.
Status & editing
queued Sprint: P&C Wave 2: Core Contracts
Edit status / sprint on the ★ Live Board → — changes are logged live with who / when / why.
Human-in-the-loop
No human tasks linked.
Findings
None recorded yet.
Concerns
None recorded yet.
Tech debt
None recorded yet.
Tools used
No tool calls recorded.
Files & artifacts
No files / artifacts recorded.
Update log
No log entries yet.