Skip to content

Commit 744edae

Browse files
committed
feat: Refactor backend architecture to utilize Pydantic for type safety and validation
- Updated requirements to include Pydantic and MCP libraries. - Removed empty __init__.py file from backend/tasks. - Added comprehensive Copilot instructions for architecture and workflows. - Introduced Pydantic-based architecture documentation for task management. - Created Unified Architecture documentation to eliminate duplication between REST and MCP. - Implemented api_decorators.py for unified operation handling with automatic schema generation. - Consolidated task management logic into tasks.py with Pydantic models for validation and serialization. - Enhanced TaskService with consolidated methods for task operations, avoiding overly granular functions. Signed-off-by: Andre Bossard <anbossar@microsoft.com>
1 parent e4ed2fc commit 744edae

11 files changed

Lines changed: 1714 additions & 174 deletions

.claude/settings.local.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
"Bash(python3:*)",
1515
"Bash(npx playwright install chromium)",
1616
"Bash(npx playwright test --project=chromium --reporter=line)",
17-
"Bash(npx playwright test:*)"
17+
"Bash(npx playwright test:*)",
18+
"Bash(find:*)",
19+
"Bash(python:*)"
1820
],
1921
"deny": [],
2022
"ask": []

.github/copilot-instructions.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copilot Instructions
2+
3+
## Architecture
4+
5+
- `backend/app.py` hosts both REST (`/api/*`) and MCP JSON-RPC (`/mcp`) on port 5001; every new capability should be exposed via the shared `@operation` decorator so both interfaces stay in sync.
6+
- Business logic lives in `backend/tasks.py` (`TaskService` plus Pydantic models) backed by an in-memory `_tasks_db`; keep it the single source of truth and seed demo data via `TaskService.initialize_sample_data()`.
7+
- The React side is feature-first: `frontend/src/App.jsx` just switches tabs while each folder under `frontend/src/features` owns its state, calculations, and FluentUI layout; `frontend/src/services/api.js` is the only place that should issue network calls.
8+
9+
## Backend Patterns
10+
11+
- Define operations with `@operation` (see `op_create_task`, `op_get_task`): annotate parameters with Pydantic models or enums so MCP schemas and REST validation are generated automatically, then build thin Quart wrappers that only handle HTTP concerns.
12+
- Keep methods like `TaskService.create_task` and `TaskService.update_task` “deep”: they already validate, mutate `_tasks_db`, and return `Task` models, so avoid splitting them into tiny helpers or duplicating validation elsewhere.
13+
- Use the provided Pydantic models (`TaskCreate`, `TaskUpdate`, `TaskStats`, `TaskFilter`) for all inputs/outputs; MCP tooling and REST serializers expect `.model_dump()` objects with these exact field names (`created_at`, `completed`, etc.).
14+
- The SSE endpoint `time_stream` streams `{"time","date","timestamp"}` JSON strings; if you change its shape, also update `connectToTimeStream` consumers and the Dashboard expectations.
15+
16+
## Frontend Patterns
17+
18+
- Feature components isolate **calculations** (pure helpers like `getTaskStats`), **actions** (API calls, event handlers), and **data** (React state) in that order; preserve that structure when extending `TaskList` or `Dashboard`.
19+
- Stick to FluentUI v9 primitives with `makeStyles`/`tokens`; prefer adjusting the `useStyles` definitions over inline styles to maintain theming consistency.
20+
- Always go through `frontend/src/services/api.js` (`fetchJSON`, `createTask`, `updateTask`, etc.); components expect rejected promises to carry friendly `Error.message`, so don’t bypass these helpers.
21+
- Task UI and tests rely on deterministic `data-testid` attributes (`task-menu-${id}`, `filter-completed`, etc.); keep them stable or update the Playwright suite alongside UI changes.
22+
- Real-time widgets follow the `connectToTimeStream` contract (subscribe in `useEffect`, capture cleanup function, surface errors via component state); reuse that approach for any new SSE sources.
23+
24+
## Workflows
25+
26+
- One-time setup: run `./setup.sh` from the repo root to create the backend venv, install frontend deps, and provision Playwright browsers.
27+
- Dev loop: `cd backend && source venv/bin/activate && python app.py` (serves on 5001) plus `cd frontend && npm run dev`; `./start-dev.sh` or the VS Code “Full Stack: Backend + Frontend” launch config will start both for you.
28+
- MCP testing uses JSON-RPC POSTs to `http://localhost:5001/mcp` (`tools/list`, `tools/call`); no extra process is required because the Quart server already exposes it.
29+
30+
## Testing
31+
32+
- E2E coverage lives in `tests/e2e/app.spec.js`; from the repo root run `npm run test:e2e` (`:ui` for interactive, `:report` to inspect results). Start both servers first to avoid cold-start delays.
33+
- The suite assumes sample tasks exist (created by `TaskService.initialize_sample_data()`), tabs are labeled via `data-testid`, and SSE data matches the backend format; keep those invariants or update the tests deliberately.
34+
- For deterministic assertions, prefer editing helpers like `waitForAppToLoad` or the shared selector strings instead of scattering hard-coded waits.
35+
36+
## Conventions
37+
38+
- Follow “Grokking Simplicity”: keep actions (I/O) in services or event handlers, calculations pure (formatting, stats), and data as plain objects/React state; this is enforced heavily in docs and existing code.
39+
- Follow “A Philosophy of Software Design”: favor deep modules (e.g., extend `TaskService` instead of sprinkling logic across routes/components) and hide complexity behind simple interfaces.
40+
- When you touch the architecture (operation decorators, unified REST/MCP flow, feature structure), update `README.md` and `UNIFIED_ARCHITECTURE.md` so future agents inherit the correct mental model.

PROJECT_STRUCTURE.md

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ Complete overview of all files and directories in this project.
66
python-quart-vite-react/
77
88
├── backend/ # Python Quart Backend
9-
│ ├── app.py # Main application file
9+
│ ├── app.py # REST API endpoints (uses tasks.service)
10+
│ ├── mcp_server.py # MCP server (uses tasks.service)
11+
│ ├── tasks/ # Reusable task management module
12+
│ │ ├── __init__.py # Module initialization
13+
│ │ └── service.py # Core business logic (deep module)
1014
│ ├── requirements.txt # Python dependencies
1115
│ └── venv/ # Virtual environment (created during setup)
1216
@@ -63,8 +67,11 @@ python-quart-vite-react/
6367

6468
| File | Purpose |
6569
|------|---------|
66-
| `backend/app.py` | Main Quart application with all API endpoints and SSE |
67-
| `backend/requirements.txt` | Python package dependencies |
70+
| `backend/app.py` | REST API endpoints using tasks.service module |
71+
| `backend/mcp_server.py` | MCP server using tasks.service module |
72+
| `backend/tasks/service.py` | Core business logic - deep module with simple interface |
73+
| `backend/tasks/__init__.py` | Module initialization file |
74+
| `backend/requirements.txt` | Python package dependencies (Quart, MCP, etc.) |
6875
| `backend/venv/` | Isolated Python environment (gitignored) |
6976

7077
### Frontend Files
@@ -119,12 +126,20 @@ python-quart-vite-react/
119126
## Key Directories Explained
120127

121128
### `/backend`
122-
Contains the Python Quart web server. This is completely independent of the frontend and provides a RESTful API.
129+
Contains the Python backend with multiple interfaces sharing the same business logic.
130+
131+
**Architecture Pattern - Deep Modules:**
132+
- `tasks/service.py` - Core business logic (calculations, actions, data)
133+
- `app.py` - REST API interface (uses tasks.service)
134+
- `mcp_server.py` - MCP interface (uses tasks.service)
123135

124136
**Main responsibilities:**
125137
- Serve API endpoints (`/api/*`)
126138
- Handle Server-Sent Events for real-time updates
127139
- Manage task data (in-memory for demo)
140+
- Demonstrate code reusability across different interfaces
141+
142+
**Key Benefit:** Business logic is written once in `tasks.service` and reused by both REST API and MCP server. Adding a new interface (CLI, GraphQL, etc.) requires zero changes to business logic!
128143

129144
### `/frontend/src/features`
130145
Feature-based organization. Each feature is self-contained:
@@ -157,6 +172,14 @@ VSCode-specific configuration for a better development experience:
157172

158173
When adding a new feature, follow this structure:
159174

175+
**Backend (modular approach):**
176+
```
177+
backend/my-feature/
178+
├── __init__.py # Module initialization
179+
└── service.py # Business logic (calculations, actions, data)
180+
```
181+
182+
**Frontend:**
160183
```
161184
frontend/src/features/my-feature/
162185
├── MyFeature.jsx # Main component
@@ -165,10 +188,14 @@ frontend/src/features/my-feature/
165188
```
166189

167190
Then:
168-
1. Add API endpoints in `backend/app.py`
169-
2. Add API client functions in `frontend/src/services/api.js`
170-
3. Import and use in `frontend/src/App.jsx`
171-
4. Add tests in `tests/e2e/`
191+
1. Create business logic in `backend/my-feature/service.py`
192+
2. Add REST API endpoints in `backend/app.py` that use `my-feature.service`
193+
3. (Optional) Add MCP tools in `backend/mcp_server.py` that use `my-feature.service`
194+
4. Add API client functions in `frontend/src/services/api.js`
195+
5. Import and use in `frontend/src/App.jsx`
196+
6. Add tests in `tests/e2e/`
197+
198+
**Key Principle:** Keep business logic separate from interface concerns. This allows the same code to be used by REST API, MCP, CLI, or any other interface!
172199

173200
## Development Workflow
174201

0 commit comments

Comments
 (0)