The Trap of Unstructured MCP Prompting
When you use Playwright MCP with Claude Code, the temptation is immediate: describe a test, get working code, move on. This works brilliantly for the first few tests. But as one developer discovered, two weeks of this "move fast" approach leads to:
- Selector sprawl: Hardcoded selectors scattered across 15+ files
- Logic duplication: The same login flow copy-pasted in 8 test files
- Zero reusability: No page objects, no shared utilities
- Fragile tests: One UI change breaks 40 tests overnight
The problem isn't Playwright MCP—it's treating MCP as a replacement for architectural thinking rather than a tool that fits inside proper architecture.
The 30-Minute Planning Framework
Before you write your first MCP prompt, implement this planning phase:
1. Map Your Pages (5 minutes)
Create a simple list:
- LoginPage
- DashboardPage
- CheckoutPage
- ProfilePage
- SettingsPage
Each becomes a Page Object file. This is your foundation.
2. Define Reusable Actions (10 minutes)
What happens on multiple pages?
- Login/logout
- Navigation
- Form submissions
- API calls
- Data generation
These become shared utilities in tests/utils/.
3. Create Your Folder Structure (5 minutes)
Run these commands in your terminal:
mkdir -p tests/{e2e,smoke,pages,utils,fixtures}
touch tests/pages/{LoginPage,DashboardPage,CheckoutPage}.ts
touch tests/utils/{auth,api,helpers}.ts
4. Document Your Architecture (10 minutes)
Create a TEST_ARCHITECTURE.md file:
# Test Architecture
## Pages
- `LoginPage`: Handles authentication selectors and methods
- `DashboardPage`: Main dashboard interactions
- `CheckoutPage`: Checkout flow logic
## Utilities
- `auth.ts`: Login/logout, session management
- `api.ts`: API helpers for test data setup
- `helpers.ts`: Common assertions and waits
## Conventions
- All selectors defined in page objects
- No hardcoded selectors in test files
- Use fixtures for test data
How to Prompt MCP with Structure
Now when you use Claude Code with Playwright MCP, your prompts become specific and architectural:
Instead of:
Generate a test for user checkout
Use:
Generate a checkout test that:
1. Uses the existing LoginPage from tests/pages/LoginPage.ts for authentication
2. Uses the CheckoutPage object (create it in tests/pages/CheckoutPage.ts if it doesn't exist)
3. Follows our selector pattern: data-testid attributes where possible
4. Uses the auth utility from tests/utils/auth.ts for test user setup
5. Places the test file in tests/e2e/checkout.spec.ts
Or use this CLAUDE.md directive:
## Playwright Test Generation Rules
When generating Playwright tests:
1. Always use existing page objects from tests/pages/
2. Create new page objects in tests/pages/ with descriptive class names
3. Extract reusable logic to tests/utils/
4. Use data-testid selectors when available
5. Follow the folder structure: e2e for end-to-end, smoke for critical paths
6. Reference TEST_ARCHITECTURE.md for conventions
The Maintenance Payoff
This 30-minute investment pays off immediately:
- One change, one fix: Update a selector in the page object → all tests using it are fixed
- New team member onboarding: They understand the structure in 5 minutes
- Consistent prompting: Every MCP request reinforces the architecture
- Scalable test suite: Add 100 more tests without increasing maintenance burden
The One Rule
Never open Claude Code with Playwright MCP until you've spent 30 minutes on planning. Treat MCP as a code generator that fills your architecture—not a replacement for architectural thinking.
This follows the broader trend of MCP servers becoming more powerful but requiring more structured guidance. As we covered in "Stop Using Claude Code as a Chatbot. MCP Turns It Into an Executor," the shift from chatbot to executor requires clearer architectural boundaries.






