Metadata-Version: 2.4
Name: mcp-classroom
Version: 0.1.2
Summary: A stateless MCP server for Google Classroom — read courses, grade submissions, and auto-submit assignments.
Author-email: Muhammad Zain <zainchoudery786@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/zainf2327/mcp-classroom
Project-URL: Repository, https://github.com/zainf2327/mcp-classroom
Project-URL: Bug Tracker, https://github.com/zainf2327/mcp-classroom/issues
Keywords: mcp,google-classroom,llm,ai,education,model-context-protocol
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Topic :: Education
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: mcp>=1.0.0
Requires-Dist: pydantic-settings>=2.2.0
Requires-Dist: google-auth>=2.28.0
Requires-Dist: google-auth-oauthlib>=1.2.0
Requires-Dist: google-api-python-client>=2.122.0

# 🎓 MCP Classroom

> A stateless, production-ready **[Model Context Protocol](https://modelcontextprotocol.io)** server for Google Classroom.  
> Connect any AI assistant directly to your courses — read rosters and assignments, auto-solve and submit student work, grade submissions, and post polished announcements.

[![PyPI](https://img.shields.io/badge/PyPI-v0.1.0-blue?logo=pypi&logoColor=white)](https://pypi.org/project/mcp-classroom/) [![Python](https://img.shields.io/badge/Python-3.10%2B-blue?logo=python&logoColor=white)](https://pypi.org/project/mcp-classroom/) [![License](https://img.shields.io/badge/License-MIT-green?logo=opensourceinitiative&logoColor=white)](https://opensource.org/licenses/MIT) ![MCP](https://img.shields.io/badge/MCP-Compatible-purple?logo=anthropic&logoColor=white)


---

## ✨ What It Does

| | |
|---|---|
| 📚 **Read** | Courses, student & teacher rosters, assignments, submissions, announcements |
| 📝 **Create** | Assignments and announcements — with optional AI content polishing |
| 🤖 **Solve & Submit** | Agents can read, solve, and autonomously turn in assignments |
| 🏆 **Grade** | Set draft and assigned grades on student submissions |
| 💬 **Prompts** | Built-in MCP prompts for solving, grading, and progress analysis |
| 📂 **Resources** | Direct context access without tool calls |
| 🔐 **Zero Setup Auth** | Pre-configured desktop OAuth — no developer console needed |

---

## 📦 Installation

```bash
pip install mcp-classroom
```

Or run directly without installing (recommended for MCP clients):

```bash
uvx mcp-classroom
```

> **Requires Python 3.10+**

---

## 🔐 Authentication

On first run, a browser window opens asking you to sign in with Google and grant Classroom permissions. Credentials are cached in `token.json` — you won't be prompted again until the token expires.

**No developer console setup required.** Pre-configured desktop OAuth ships with the package.

---

## ⚙️ Optional: LLM Integration

Some tools optionally use an LLM to polish content (e.g. rewriting assignment descriptions, adjusting announcement tone). Any **OpenAI-compatible API** is supported.

Set these environment variables to enable it:

| Variable | Description | Example |
|---|---|---|
| `LLM_API_KEY` | Your LLM provider API key | `sk-...` |
| `LLM_BASE_URL` | Base URL of the OpenAI-compatible endpoint | `https://api.openai.com/v1` |
| `LLM_MODEL_ID` | Model identifier | `gpt-4o` |

> If these are not set the server runs in **standard mode** — all tools still work, content polishing is just skipped.

---

## 🖥️ Client Setup

<details>
<summary><b>Claude Desktop</b></summary>

Edit your `claude_desktop_config.json`:
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "google-classroom": {
      "command": "uvx",
      "args": ["mcp-classroom"],
      "env": {
        "LLM_API_KEY": "YOUR_API_KEY",
        "LLM_BASE_URL": "https://api.openai.com/v1",
        "LLM_MODEL_ID": "gpt-4o"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Cursor</b></summary>

Add to `~/.cursor/mcp.json` (or via **Cursor Settings → Features → MCP → + Add New MCP Server**):

```json
{
  "mcpServers": {
    "google-classroom": {
      "command": "uvx",
      "args": ["mcp-classroom"],
      "env": {
        "LLM_API_KEY": "YOUR_API_KEY",
        "LLM_BASE_URL": "https://api.openai.com/v1",
        "LLM_MODEL_ID": "gpt-4o"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Claude Code (CLI)</b></summary>

**Without LLM:**
```bash
claude mcp add uvx -- mcp-classroom
```

**With LLM integration:**
```bash
claude mcp add uvx \
  --env LLM_API_KEY=YOUR_API_KEY \
  --env LLM_BASE_URL=https://api.openai.com/v1 \
  --env LLM_MODEL_ID=gpt-4o \
  -- mcp-classroom
```

</details>

<details>
<summary><b>VS Code — GitHub Copilot</b></summary>

Add to `.vscode/mcp.json` in your workspace (or user settings):

```json
{
  "servers": {
    "google-classroom": {
      "type": "stdio",
      "command": "uvx",
      "args": ["mcp-classroom"],
      "env": {
        "LLM_API_KEY": "YOUR_API_KEY",
        "LLM_BASE_URL": "https://api.openai.com/v1",
        "LLM_MODEL_ID": "gpt-4o"
      }
    }
  }
}
```

</details>

<details>
<summary><b>VS Code — Continue Extension</b></summary>

Add to `~/.continue/config.json`:

```json
{
  "mcpServers": [
    {
      "name": "google-classroom",
      "command": "uvx",
      "args": ["mcp-classroom"],
      "env": {
        "LLM_API_KEY": "YOUR_API_KEY",
        "LLM_BASE_URL": "https://api.openai.com/v1",
        "LLM_MODEL_ID": "gpt-4o"
      }
    }
  ]
}
```

</details>

<details>
<summary><b>Windsurf</b></summary>

Edit `~/.codeium/windsurf/mcp_config.json`:

```json
{
  "mcpServers": {
    "google-classroom": {
      "command": "uvx",
      "args": ["mcp-classroom"],
      "env": {
        "LLM_API_KEY": "YOUR_API_KEY",
        "LLM_BASE_URL": "https://api.openai.com/v1",
        "LLM_MODEL_ID": "gpt-4o"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Antigravity</b></summary>

Go to **Settings → MCP Servers → Add Server** and paste:

```json
{
  "mcpServers": {
    "google-classroom": {
      "command": "uvx",
      "args": ["mcp-classroom"],
      "env": {
        "LLM_API_KEY": "YOUR_API_KEY",
        "LLM_BASE_URL": "https://api.openai.com/v1",
        "LLM_MODEL_ID": "gpt-4o"
      }
    }
  }
}
```

</details>

---

## 🛠️ Tools

### Courses

#### `list_google_courses`
Lists all active Google Classroom courses for the authenticated user.

**Returns:** Course ID, name, section, description, and link.  
**Arguments:** None  
**Constraints:** None.

---

### Roster

#### `list_google_students`
Lists all students enrolled in a course.

**Returns:** User ID, full name, email address.

| Argument | Type | Description |
|---|---|---|
| `course_id` | `string` | ID of the course |

#### `list_google_teachers`
Lists all teachers and co-teachers of a course.

**Returns:** User ID, full name, email address.

| Argument | Type | Description |
|---|---|---|
| `course_id` | `string` | ID of the course |

---

### Assignments

#### `list_google_coursework`
Lists every assignment in a course with full details and the authenticated user's submission state.

**Returns:** ID, title, description, max points, due date, link, submission state (`NEW` / `CREATED` / `TURNED_IN` / `RETURNED`), submission ID, and a pre-built `solving_prompt` ready to feed into any LLM.

| Argument | Type | Description |
|---|---|---|
| `course_id` | `string` | ID of the course |

#### `list_upcoming_assignments`
Same as above but filtered to **pending-only** work, sorted by closest due date first. Skips anything already `TURNED_IN` or `RETURNED`.

| Argument | Type | Description |
|---|---|---|
| `course_id` | `string` | ID of the course |

#### `create_google_coursework`
Creates and publishes a new assignment in a course.

**Returns:** Success status, new assignment ID, direct link.  
**LLM Enhancement:** If `LLM_API_KEY` is set, the description is automatically restructured with headings, bullet points, a grading rubric, and a due date reminder.

| Argument | Type | Required | Description |
|---|---|---|---|
| `course_id` | `string` | ✅ | ID of the course |
| `title` | `string` | ✅ | Assignment title |
| `description` | `string` | ❌ | Assignment instructions |
| `max_points` | `integer` | ❌ | Maximum grade (default: `100`) |
| `due_date` | `string` | ❌ | `YYYY-MM-DD` |
| `due_time` | `string` | ❌ | `HH:MM` (24-hour) |

> ⛔ **Teacher accounts only.** Students receive `403 Forbidden`.  
> ⚠️ Only assignments created through this tool can be graded via `grade_google_submission`.

---

### Submissions

#### `list_google_submissions`
Lists every student's submission record for an assignment.

**Returns:** Submission ID, user ID, state, draft grade, assigned grade, submitted text (short answers), and link.

| Argument | Type | Description |
|---|---|---|
| `course_id` | `string` | ID of the course |
| `coursework_id` | `string` | ID of the assignment |

> Students see only their own submission. Teachers see all.

#### `submit_student_assignment`
Attaches an answer and turns in an assignment on behalf of the authenticated student.

Supports two submission types:
- **`text_answer`** — for `SHORT_ANSWER_QUESTION` coursework
- **`attachment_url`** — for `ASSIGNMENT` coursework (GitHub link, Google Doc, etc.)

The tool automatically calls `turnIn` after attaching the answer.

| Argument | Type | Required | Description |
|---|---|---|---|
| `course_id` | `string` | ✅ | ID of the course |
| `coursework_id` | `string` | ✅ | ID of the assignment |
| `text_answer` | `string` | ❌ | Text answer (SHORT_ANSWER_QUESTION only) |
| `attachment_url` | `string` | ❌ | URL to attach (ASSIGNMENT type only) |

> ⛔ **Student accounts only.** Teacher accounts have no submission record.  
> ⛔ **Only works on assignments created by this server.** Assignments made in the Classroom UI return `403 @ProjectPermissionDenied` — this is a permanent Google API restriction.

#### `grade_google_submission`
Sets a draft and/or assigned grade on a student's submission.

**Returns:** Updated submission with confirmed grade values.

| Argument | Type | Required | Description |
|---|---|---|---|
| `course_id` | `string` | ✅ | ID of the course |
| `coursework_id` | `string` | ✅ | ID of the assignment |
| `submission_id` | `string` | ✅ | ID of the student's submission |
| `draft_grade` | `float` | ✅ | Grade visible only to the teacher |
| `assigned_grade` | `float` | ❌ | Grade returned to the student |

> ⛔ **Teacher accounts only.**  
> ⛔ **Only works on assignments created by this server.** The Google Classroom API permanently restricts `patch` to the same Developer Console project that created the coursework — no scope or permission can override this.

---

### Announcements

#### `list_google_announcements`
Lists all announcements from the course stream.

**Returns:** ID, full text, creation timestamp, link.

| Argument | Type | Description |
|---|---|---|
| `course_id` | `string` | ID of the course |

#### `create_google_announcement`
Posts a new announcement to the course stream.

**Returns:** Success status, announcement ID, link.  
**LLM Enhancement:** If `LLM_API_KEY` is set, the text is rewritten in the requested tone before posting.

| Argument | Type | Required | Description |
|---|---|---|---|
| `course_id` | `string` | ✅ | ID of the course |
| `text` | `string` | ✅ | Announcement content |
| `tone` | `string` | ❌ | e.g. `professional`, `friendly`, `urgent` |

> ⛔ **Teacher accounts only.**

---

## 📂 Resources

Query structured Classroom data directly as context — no tool call needed.

| URI | Description |
|---|---|
| `googleclassroom://courses` | All active courses |
| `googleclassroom://course/{course_id}/coursework` | All assignments in a course |
| `googleclassroom://course/{course_id}/announcements` | All announcements in a course |
| `googleclassroom://course/{course_id}/roster` | Students and teachers in a course |
| `googleclassroom://course/{course_id}/upcoming` | Pending assignments sorted by due date |

---

## 💬 Prompts

Built-in MCP Prompts that guide an AI through complex multi-step Classroom workflows.

**`solve_assignment_prompt`**  
Prepares an AI to write a complete solution to an assignment. Includes title, max points, due date, instructions, and output format guidance. Every assignment returned by `list_google_coursework` already includes a pre-built version of this prompt in the `solving_prompt` field.

**`grade_submission_prompt`**  
Guides an AI through evaluating submitted work against the assignment rubric. Pass alongside submission data from `list_google_submissions` to get a suggested grade and feedback before calling `grade_google_submission`.

**`analyze_student_progress_prompt`**  
Helps an AI review a student's grades across all assignments and produce a personalized progress report or study plan.

---

## 🔒 Constraints at a Glance

| Tool | Requires Teacher | Requires Student | Created by This Server |
|---|:---:|:---:|:---:|
| `list_google_courses` | | | |
| `list_google_students` | | | |
| `list_google_teachers` | | | |
| `list_google_coursework` | | | |
| `list_upcoming_assignments` | | | |
| `list_google_submissions` | | | |
| `list_google_announcements` | | | |
| `create_google_coursework` | ✅ | | |
| `create_google_announcement` | ✅ | | |
| `submit_student_assignment` | | ✅ | ✅ Required |
| `grade_google_submission` | ✅ | | ✅ Required |

> **Why "Created by This Server"?**  
> Google Classroom enforces that `turnIn`, `modifyAttachments`, and grade `patch` can only be called by the same Developer Console project that created the assignment. This is a hard platform rule — it cannot be bypassed with any scope or permission.

---

## 🗂️ OAuth Scopes

| Scope | Purpose |
|---|---|
| `classroom.courses.readonly` | Read course list |
| `classroom.coursework.students` | Read/write assignments and grade submissions (teacher) |
| `classroom.coursework.me` | Read/write own submissions, turn in work (student) |
| `classroom.rosters.readonly` | Read student and teacher rosters |
| `classroom.announcements` | Read and post announcements |
| `classroom.profile.emails` | Read user email addresses |

---

## 📄 License

MIT © [Muhammad Zain](https://github.com/zainf2327)
