01 What students build
This chapter upgrades the bug triage crew into a real deliverables factory. A MCPServerAdapter launches uvx mcp-atlassian as a subprocess and converts its Jira tools into CrewAI tools, injected only into Agent 1. The other three agents are pure writers: ISTQB-style test plan, detailed test case tables, and POM-structured Playwright code, each task saving its own markdown file via output_file.
MCP Tools in a Crew
mcp-atlassian exposes ~49 Jira tools. The pipeline filters to just jira_get_issue and jira_search so tool schemas do not blow Groq's free-tier token budget.
Templated Test Plans
Agent 2's backstory embeds a strict 12-section template: scope, strategy, entry and exit criteria, risk table, schedule, sign-off. Output is executable documentation, not prose.
Rate-Limit Engineering
Real free-tier constraints: max_rpm=4, a model swap from gpt-oss-120b (8k TPM) to llama-3.3-70b (30k TPM), and a patched LLM class that strips fields Groq rejects.
02 Architecture
03 Live demo (simulated with sample data)
This is a UI walkthrough with pre-baked sample data. In the course you run the real pipeline: CrewAI + mcp-atlassian against your Jira workspace, with the three artifacts landing in ./output/.
04 Inputs & outputs
What goes in
- A Jira ticket ID as a CLI argument (
python main.py VWO-48) - Jira credentials passed to the MCP server via env vars
- The 12-section test plan template in Agent 2's backstory
- Groq API key for llama-3.3-70b-versatile
What comes out
output/test_plan.md· complete 12-section planoutput/test_cases.md· 12-15 cases in a priority tableoutput/playwright_tests.md· runnable POM TypeScript- A ticket analysis with requirements, edge cases, and risks
05 How it's built
StdioServerParameters so CrewAI launches uvx mcp-atlassian as a subprocess with Jira credentials in its env.MCPServerAdapter context manager: it discovers ~49 Jira tools and converts them to CrewAI-compatible tools.jira_get_issue and jira_search so tool schemas stay under Groq's free-tier TPM budget.max_iter=10.context=[...] and give each writer task an output_file under ./output/.max_rpm=4 and kick it off from main.py with the ticket ID.