Skip to main content

MCP Server E2E Test Plan

Key paths to validate on staging before each production deploy.

V1 — API Key Authentication

#PathExpectedSLA
1POST /mcp with valid V1 API key + { method: "initialize" }HTTP 200, mcp-session-id header in response< 2s
2POST /mcp with invalid/missing keyHTTP 401< 1s
3POST /mcp (session exists) + { method: "tools/list" }JSON with expected tools array< 2s
4get_products call on merchant sessionReturns business-scoped product data< 3s
5get_products called with wrong businessId (not in principal)Tool handler returns error content< 2s
6Session initialized without pos:write scopetools/list does not include create_order or void_transaction; forced calls fail because the tool is not registered on that session< 1s
7DELETE /mcp with valid Authorization + session IDSession closed, subsequent requests return 400< 1s

V2 — OAuth Token Exchange

#PathExpectedSLA
8POST /mcp/token with valid Firebase ID tokenHTTP 200, accessToken JWT returned with authorizedBusinessIds< 3s
9POST /mcp/token with expired/invalid Firebase tokenHTTP 401< 2s
10POST /mcp/token for user with no business membershipsHTTP 403< 2s
11Session opened with V2 token → tools/list includes set_active_business (multi-business user)Tool present in list< 2s
12set_active_business with valid businessIdactiveBusinessId updated in session; next domain tool call returns data for the new business< 2s
13set_active_business with unauthorized businessIdError content in response; session activeBusinessId unchanged< 1s
14V2 session: principal written to Redis on initializeGET mcp:session:{sid} in Redis returns valid JSON principal with correct TTL< 1s
15set_active_tenant (platform_operator key) with valid businessIdSubsequent get_products call is scoped to the new tenant< 2s

PSA Tools

#PathExpectedSLA
16V2 merchant token calls log_hours with stepId and hours but no userIdTime entry created for the authenticated principal user< 3s
17API key with no createdBy calls log_hours without userIdTool returns validation/error content because the principal has no resolvable user ID< 1s
18platform_operator calls log_hours with explicit userIdTime entry created for the supplied user ID< 3s

Intent Tools (pos:intents scope)

#PathExpectedSLA
19Merchant session with pos:intentstools/listAll 4 intent tools present< 2s
20tenant_developer session → tools/listIntent tools NOT present< 2s
21summarize_day callReturns totalRevenue, orderCount, topProducts, lowStockAlertCount< 5s
22summarize_day for date with no transactionsReturns zeros without error< 3s
23get_client_health with valid implementation IDReturns phase, completionPct, hoursBurned, hoursEstimated, openBlockers< 5s

Prompts and Resources

#PathExpectedSLA
24prompts/list after initializeReturns 8 prompt shortcuts: daily_briefing, end_of_day_report, weekly_review, monthly_performance, low_stock_check, top_sellers, restock_plan, sales_by_location< 2s
25prompts/get for daily_briefing with no argumentsReturns one user-role message with instructions to call summarize_day and optionally get_low_stock_alerts< 2s
26resources/list after initializeReturns the 3 static docs resources only: flowpos://docs/quick-start, flowpos://docs/prompt-guide, flowpos://docs/currency-guide< 2s
27resources/read for flowpos://docs/quick-startReturns markdown capability guidance and prompt shortcut table< 2s
28resources/read for flowpos://business/profileReturns template guidance that tells the assistant to call get_active_business; it does not return live business data directly< 2s
29resources/read for flowpos://inventory/low-stockReturns template guidance that tells the assistant to call get_inventory_health and get_low_stock_alerts; it does not return live inventory data directly< 2s