pw-mcp
<div align="center">
# pw-mcp
**Physics Wallah Study MCP Server**
Schedule tracking, backlog management, and progress monitoring for PW students — powered by the Model Context Protocol.
[](https://www.python.org/downloads/)
[](LICENSE)
[](#testing)
</div>
---
## What it does
Connect your AI assistant to your PW study data. Ask questions like:
- *"What classes do I have today?"*
- *"How much physics backlog do I have?"*
- *"Generate a 7-day study plan for 4 hours/day"*
- *"Mark the chemical bonding lecture as done"*
The server exposes **15 MCP tools** that any MCP-compatible client (Claude, opencode, etc.) can call.
---
## Quick Start
```bash
# Clone
git clone https://github.com/vspcoderz/pw-mcp.git
cd pw-mcp
# Install
uv venv && source .venv/bin/activate
uv sync
# Run (mock mode — no credentials needed)
uv run pw-mcp
```
That's it. Mock mode works offline with realistic sample data across Physics, Chemistry, and Mathematics.
---
## Real PW Integration
To connect to your actual PW account:
1. **Get your API token:**
- Log into [pw.live](https://pw.live) in your browser
- Open DevTools → Network tab
- Filter by `token`, find the `verify-token` request
- Copy the `Authorization: Bearer <token>` value
2. **Configure:**
```bash
cp .env.example .env
```
Edit `.env`:
```
PW_PROVIDER=pw
PW_API_TOKEN=your_token_here
PW_DEFAULT_BATCH=your-batch-slug
```
3. **Run:**
```bash
uv run pw-mcp
```
**How it works:**
- The real provider uses PW's `weekly-schedule` endpoint to fetch today's and upcoming lectures — the same data the PW app shows in the "Weekly Schedule" tab
- Falls back to the topics/contents endpoint for older lectures
- Progress tracking is stored locally in SQLite (PW doesn't expose a server-side progress API)
- Set `PW_DEFAULT_BATCH` to your batch slug (the part after `/batches/` in the PW URL)
---
## Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `PW_PROVIDER` | `mock` | `mock` (offline) or `pw` (real API) |
| `PW_API_TOKEN` | — | Bearer token for pw.live |
| `PW_API_BASE_URL` | — | Override API base URL |
| `PW_DEFAULT_BATCH` | `arjuna-jee-2027-243495` | Batch slug for schedule fetching |
| `PW_TIMEOUT` | `20` | Request timeout in seconds |
| `DATABASE_PATH` | `./data/pw_mcp.db` | SQLite database path |
| `TIMEZONE` | `Asia/Kolkata` | Timezone for schedule calculations |
| `LOG_LEVEL` | `INFO` | Logging verbosity |
---
## Architecture
```
┌─────────────────────────────────────────────┐
│ MCP Client │
│ (Claude, opencode, etc.) │
└──────────────────┬──────────────────────────┘
│ stdio
┌──────────────────▼──────────────────────────┐
│ MCP Server (server.py) │
├─────────────┬───────────────┬───────────────┤
│ Schedule │ Backlog │ Progress │
│ Service │ Service │ Service │
├─────────────┴───────────────┴───────────────┤
│ PWProvider (ABC) │
├──────────────────┬──────────────────────────┤
│ MockPWProvider │ RealPWProvider │
│ (offline) │ (pw.live API) │
└──────────────────┴──────────────────────────┘
```
**Design principle:** Services never know where data comes from. The provider abstraction makes swapping mock ↔ real trivial.
---
## MCP Tools
### Schedule
| Tool | Description |
|------|-------------|
| `get_today_schedule` | Today's lectures |
| `get_upcoming_schedule` | Next N days (1-30) |
| `get_schedule` | Custom date range |
| `get_next_lecture` | Next upcoming incomplete lecture |
| `get_lecture` | Single lecture by ID |
### Backlog
| Tool | Description |
|------|-------------|
| `get_backlog` | Incomplete past lectures (filterable) |
| `get_subject_backlog` | Backlog for a subject |
| `get_chapter_backlog` | Backlog for a chapter |
| `get_backlog_summary` | Aggregate statistics |
| `get_oldest_backlog_lecture` | Oldest incomplete lecture |
### Progress
| Tool | Description |
|------|-------------|
| `mark_lecture_completed` | Mark lecture done |
| `mark_lecture_incomplete` | Mark lecture not done |
| `update_watched_minutes` | Update watch progress |
| `get_completion_stats` | Overall progress |
### Planning
| Tool | Description |
|------|-------------|
| `generate_study_plan` | Personalized study plan from backlog |
---
## MCP Client Setup
### opencode
Add to your `opencode.json`:
```json
{
"mcp": {
"pw": {
"type": "stdio",
"command": "uv",
"args": ["run", "--directory", "/path/to/pw-mcp", "pw-mcp"]
}
}
}
```
### Claude Desktop
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"pw": {
"command": "uv",
"args": ["run", "--directory", "/path/to/pw-mcp", "pw-mcp"]
}
}
}
```
### MCP Inspector
Test with the official inspector:
```bash
npx @modelcontextprotocol/inspector uv run pw-mcp
```
---
## Testing
```bash
uv run pytest -v
```
78 tests covering:
- Schedule queries (today, upcoming, date range)
- Backlog calculation (subject/chapter filtering, summary)
- Progress tracking (mark complete/incomplete, watched minutes)
- SQLite persistence (upsert, delete, reconnection)
- Study plan generation (hours constraint, subject filter)
- Model validation and timezone handling
- Provider selection and configuration
---
## Project Structure
```
pw-mcp/
├── pyproject.toml
├── .env.example
├── src/pw_mcp/
│ ├── server.py # MCP tool definitions + wiring
│ ├── config.py # pydantic-settings config
│ ├── exceptions.py # Custom exceptions
│ ├── models/ # Pydantic data models
│ │ ├── lecture.py
│ │ ├── schedule.py
│ │ ├── backlog.py
│ │ └── progress.py
│ ├── providers/ # Data source abstraction
│ │ ├── base.py # PWProvider ABC
│ │ ├── mock.py # Offline with sample data
│ │ └── pw.py # Real pw.live API
│ ├── services/ # Business logic
│ │ ├── schedule.py
│ │ ├── backlog.py
│ │ ├── progress.py
│ │ └── study_plan.py
│ ├── storage/ # SQLite persistence
│ │ └── sqlite.py
│ └── utils/ # Date/formatting helpers
│ ├── dates.py
│ └── formatting.py
├── tests/ # pytest suite
└── docs/
└── pw-api.md # PW API reverse-engineering docs
```
---
## PW API Notes
See [`docs/pw-api.md`](docs/pw-api.md) for full endpoint documentation.
**Key findings:**
- PW uses OTP-based auth (no username/password)
- Weekly schedule is available via `/v3/batches/{slug}/weekly-schedule`
- Progress tracking is client-side only
- Two platforms: `pw.live` (school/exam prep) and `pwskills.com` (professional courses)
---
## License
MIT
TDQS
Scored across 15 tools
Tools are mostly distinct by resource and filter: schedule queries differ by time range, and backlog queries differ by subject/chapter/aggregate. Minor ambiguity exists between get_next_lecture and get_oldest_backlog_lecture, and get_backlog vs get_backlog_summary, but descriptions largely resolve this.
All tool names follow a consistent verb-first pattern: get_, mark_, update_, generate_. Nouns are clear and singular, with no mixed casing or vague action verbs.
15 tools is at the upper edge of well-scoped, and most tools serve a distinct purpose. A few convenience getters (today's schedule, upcoming schedule, date-range schedule) could be consolidated, but the count is still reasonable for the domain.
The surface covers schedule lookup, backlog filtering, completion state changes, watched minutes, stats, and study plan generation. Minor gaps like explicit subject/chapter listing or a way to view all lectures outside a date range are workable around.