Testing map (FE / BE / MCP / CLI)

July 11, 2026 · View on GitHub

Status: Living map — fill Integration scenarios with product owner input
Related: DEVELOPMENT.md, MCP_TOOL_OPTIMIZATION.md, playbook user-path-integration-smoke.md

How we test Agent Deck today, what is missing after the 1.3.0 MCP tool surface change, and how we should grow tests without over-building.


Layers (what each proves)

Unit (fast, no ports)
  shared schemas, pure helpers, DB managers, tool profile math

Component / route (in-process)
  React hooks, Fastify routes with temp DB, CLI setup writers

Protocol / HTTP (real ports, stub peers)
  MCP streamable HTTP: initialize → tools/list → tools/call
  Backend health + scoped routes

Release / user path (packaged artifact)
  npm pack + setup + statusline stdout contract
LayerRunnerWhen it runs
Unit + componentnpm test (Vitest via Turbo)Every PR / local
Launch smokenpm run smoke:devAfter BE/MCP changes (manual / agent rule)
Release smokenpm run release:smoke (inside build:release)Before publish

As-built inventory

Shared (packages/shared)

AreaFiles (examples)Coverage
Schemas / validationschemas/*.test.ts, utils/validation.test.tsStrong
Playbook deps, credentials, OAuth sessionutils/playbook-dependencies.test.ts, etc.Strong

Backend (packages/backend)

AreaFiles (examples)Coverage
SQLite / decks / credentialsmodels/database*.test.tsStrong
Vault / OAuthvault/*.test.tsStrong
Playbooksplaybooks/playbook-manager.test.tsStrong
Service manager / MCP clientservices/*.test.tsMedium (mocked peers)
Scope / live display / badgesscope/*.test.ts, routes/scope.bindings.test.tsStrong
MCP tools (logic)mcp-tools/profile.test.ts, deck-card-ops.test.tsNew — unit only
MCP protocol (HTTP)mcp-server.http.test.tsPartial — session, health, tools/list names, bind badge
CLI admin (delete)cli-runtime.test.tsNew — unit against temp DB

MCP HTTP tests today assert:

  • Multi-session initialize
  • GET /mcp SSE for Claude
  • Reject calls without session
  • Default profile tool names (manage_deck_card, create_deck; no list_playbooks / delete_*)
  • bind_workspace → live-display badge (stub backend)

MCP HTTP tests do not yet assert:

  • Full agent flows: bind → get_bound_deckmanage_deck_cardget_playbook / update_playbook
  • list_collection / register_* against real API
  • Profile matrix (runtime / legacy) end-to-end
  • Error shapes (NOT_BOUND, playbook dependency on delete via CLI)
  • Proxy call_service_tool (needs fake upstream MCP)

CLI (packages/cli)

AreaFilesCoverage
Setup / harness / statusline / menubar*.test.tsStrong for install contracts
Release user pathrelease-integration.test.ts + scripts/release-smoke.shStrong for statusline
Collection admin (`serviceplaybookdeck delete`)

Frontend (apps/agent-deck)

AreaFilesCoverage
Hooks (WebSocket, drag-drop)test/hooks/*.test.tsxMedium
Deck fan layout mathcomponents/deck-fan.test.tsStrong for layout
Live bindings display helperslib/live-bindings.test.tsStrong for formatting
Pages / modalsThin (no full-page render suite)
Deck link/unlink (S11)test/hooks/useDragAndDrop.deck-link.test.tsxAuto — Vitest + Testing Library + jsdom

Framework: Vitest + React Testing Library + jsdom (already in apps/agent-deck). No Playwright — same runner as BE/CLI, included in npm test / Turbo CI.


MCP testing — best practice (what works here)

Hosts (Cursor / Claude) are not in CI. Treat MCP as a protocol server we own:

PracticeHow
1. Unit the handlersPure functions (executeManageDeckCard, profile lists) — no ports
2. Contract-test the wireReal AgentDeckMCPServer on ephemeral port; JSON-RPC initializetools/listtools/call
3. Stub the backendTiny http.createServer (already in mcp-server.http.test.ts) — assert paths/bodies, not full SQLite unless needed
4. Snapshot the catalogtools/list names must match profile (guards accidental tool sprawl / renames)
5. One golden agent pathBind → get_bound_deck → (optional manage_deck_card) → get_playbook — against stub or temp DB
6. Do not wait on host list_changedDynamic tools are host-blocked; do not invent flaky host tests

Anti-patterns: only unit-testing registration without tools/list; only manual Cursor clicks; testing OAuth browser flows in MCP suite.


Gaps after 1.3.0 (priority)

PriorityGapSuggested home
P0Golden MCP path: bind + get_bound_deck + manage_deck_card link/unlinkmcp-server.http.test.ts + richer stub
P0Catalog snapshot per profile (runtime / standard / legacy)profile.test.ts (done) + HTTP list for standard (partial)
P1CLI `serviceplaybook
P1Harness template never mentions removed toolsagent-harness.test.ts (partial — checks get_bound_deck)
P2FE: deck editor link/unlink still works with API (not MCP)Component or route tests; optional later Playwright
P2Release smoke: harness file contains get_bound_deck after setuprelease-smoke.sh

Integration scenarios (fill with product owner)

Use this table to decide what we automate next. Mark Auto (CI), Smoke (release script), or Manual.

IDScenarioActorSurfaceExpectedAuto / Smoke / Manual
S1Fresh install → setup cursor → harness names new toolsUserCLIget_bound_deck in rule file; no list_playbooksSmoke (release-smoke.sh) + Auto (agent-harness.test.ts)
S2Agent bind workspace + deckAgentMCPdisplay_summary + live-displayAuto (golden-path.http.test.ts)
S3Capability rescueAgentMCPlink service; get_bound_deck; call_service_toolAuto
S4Playbook discover + followAgentMCPtriggers on get_bound_deck; get_playbook bodyAuto
S5Playbook self-improve (proposal queue)AgentMCP + dashboardpropose_playbook_patch → review → accept; genesis + update casesManualLEARNING_LOOP_TEST_SCENARIOS.md
S6Link existing card to deckAgentMCPmanage_deck_card linkAuto
S7Unlink cardAgentMCPunlink; still in list_collectionAuto
S8Create deck then bindAgentMCPcreate_deck + bind known deckAuto
S9Delete service blocked by playbook depUserCLIdelete fails with messageAuto (cli-runtime.test.ts)
S10Delete playbookUserCLIdelete succeedsAuto (cli-runtime.test.ts)
S11Dashboard drag card onto deckUserFE + APIlink/unlink service, credential, playbook via RESTAuto (useDragAndDrop.deck-link.test.tsx)
S12Old playbook still says list_playbooksAgentMCPtool missing — migration doc / legacy profileManual / CHANGELOG
S13Stale host tool cache after upgradeUserHostrestart Cursor/Claude requiredManual / CHANGELOG
S14Statusline bound line (badge + deck name)HostCLIrunStatusline prints displayLine from /api/scope/displayAuto (display-surfaces.http.test.ts)
S15Statusline offline when API downHostCLI◆ Agent Deck offlineAuto
S16Menubar live sessionsHostCLIrunMenubar renders /api/scope/bindingsAuto
S17Menubar offlineHostCLI◆ off title, no badgeAuto
S18Menubar plugin scriptUserCLIinstall writes executable agent-deck.3s.sh calling menubarSmoke + Auto (menubar-setup.test.ts)

Test files (1.3.0)

FileScenarios
packages/backend/src/mcp-tools/test-harness.tsShared MCP HTTP helpers
packages/backend/src/mcp-tools/golden-path.http.test.tsS2–S8 + catalog snapshot
packages/backend/src/mcp-tools/profile.test.tsProfile tool lists
packages/backend/src/mcp-tools/deck-card-ops.test.tsLink/unlink/reorder unit
packages/backend/src/cli-runtime.test.tsS9–S10
packages/cli/src/agent-harness.test.tsS1 template names
packages/cli/src/collection-admin.test.tsCLI arg wiring
apps/agent-deck/src/test/hooks/useDragAndDrop.deck-link.test.tsxS11 FE link/unlink
packages/cli/src/display-surfaces.http.test.tsBound statusline + menubar vs HTTP stub
packages/cli/src/statusline*.test.ts, menubar*.test.tsUnit render, setup, host stdin contract
scripts/release-smoke.shS1 harness + statusline stdout + menubar plugin script

Commands cheat sheet

npm test                                    # all packages
npm test --workspace packages/backend       # includes MCP HTTP + mcp-tools
npm test --workspace packages/cli
npm test --workspace apps/agent-deck
npm run smoke:dev                           # live ports health
npm run release:smoke                       # pack + setup user path