Skip to main content
Glama
README.md
# classroom-mcp-server

An MCP server that lets Claude read and write your **Google Classroom** data — courses, topics, coursework (assignments), materials (lessons), announcements, rosters, submissions, and all their attachments.

Works with both **Claude Code CLI** and **Claude Desktop** (stdio transport).

---

## What it can do

**Read tools**
- `classroom_whoami` — show which Google account is currently authorized (confirm it holds your classes)
- `classroom_list_courses` — your classes
- `classroom_list_topics` — topic/section headers in a course
- `classroom_list_coursework` — assignments (with due dates, points, attachments, topic)
- `classroom_list_materials` — posted lesson materials (CourseWorkMaterials)
- `classroom_list_announcements` — stream announcements
- `classroom_list_roster` — students or teachers
- `classroom_list_submissions` — your submissions + grades for an assignment
- `classroom_dump_course` — **everything** for one course in a single call: topics with their coursework + materials nested, plus announcements, each with attachments
- `drive_fetch_file_content` — read the **text content** of an attachment by its Drive file id (so the model can actually see what's inside Docs/Sheets/Slides/etc.)

**Write tools**
- `classroom_attach_to_submission` — attach a Drive file or link to your work
- `classroom_turn_in_submission` — turn in an assignment
- `classroom_reclaim_submission` — unsubmit to edit
- `classroom_create_topic` — *(teacher accounts)* create a topic
- `classroom_create_announcement` — *(teacher accounts)* post an announcement

> ⚠️ **Student accounts are read-restricted by Google.** You can read all of *your own* data and submit/reclaim your own work. Creating topics/announcements and seeing other students' submissions require teacher rights on the course — those calls return a clear permission error otherwise.
>
> Note: "subjects" and "lessons" aren't native Classroom objects. Teachers model them with **Topics** + **CourseWorkMaterials**, which is what the topic/materials tools surface.

---

## One-time setup

### 1. Enable the API + make an OAuth client
1. Go to [Google Cloud Console](https://console.cloud.google.com/) → create/select a project.
2. **APIs & Services → Library →** enable **Google Classroom API**.
3. **APIs & Services → OAuth consent screen →** configure it (External is fine for personal use). Add yourself as a **Test user**.
4. **APIs & Services → Credentials → Create Credentials → OAuth client ID →** application type **Desktop app**.
5. Download the JSON.

### 2. Drop the credentials in place
```bash
mkdir -p ~/.config/classroom-mcp
cp ~/Downloads/client_secret_*.json ~/.config/classroom-mcp/credentials.json
```

### 3. Build and authorize
```bash
cd classroom-mcp-server
npm install
npm run build
npm run auth      # opens a consent URL, catches the redirect, saves token.json
```

The auth script binds a loopback listener on an OS-assigned free port and tells Google to redirect there. Desktop-app OAuth clients may use any port on `127.0.0.1`, so there is nothing to configure and no elevated permission needed. The consent screen is bound to a random `state` value, and a redirect that doesn't carry it back is refused.

`token.json` holds a refresh token — a standing grant to your Classroom and Drive. It is written `0600`, and `~/.config/classroom-mcp/` is kept `0700`.

### Pointing it at the right Google account

On the consent screen, **pick the Google account that actually holds your classes** — that's the account the server reads from. To confirm afterwards, run the `classroom_whoami` tool (just ask Claude "which classroom account am I on?"). To switch accounts, delete the cached token and re-authorize:
```bash
rm ~/.config/classroom-mcp/token.json
npm run auth      # choose the correct account this time
```

### Reading attachment contents

Listing tools return attachments as references (Drive file id, link, etc.). To read what's *inside* a Drive attachment, take its `driveFile.driveFile.id` from any coursework/material/dump result and pass it to `drive_fetch_file_content`. Google Docs come back as plain text, Sheets as CSV, Slides as text; PDFs and images return metadata + a link rather than text. In practice you can just ask Claude "open the attachment on assignment X" and it will chain the calls.

---

## Connecting it

### Claude Code CLI
```bash
claude mcp add classroom -- node /absolute/path/to/classroom-mcp-server/dist/index.js
```

### Claude Desktop
Edit `claude_desktop_config.json` (Settings → Developer → Edit Config):
```json
{
  "mcpServers": {
    "classroom": {
      "command": "node",
      "args": ["/absolute/path/to/classroom-mcp-server/dist/index.js"]
    }
  }
}
```
Restart Claude Desktop.

---

## Scopes / read-only mode

Scopes live in `src/constants.ts`. The defaults request: read of course structure, read/write of your own coursework + topics/announcements, **read-only Drive access** (`drive.readonly`, needed so `drive_fetch_file_content` can open arbitrary Classroom attachments — `drive.file` wouldn't see files the app didn't create), and **userinfo** (so `classroom_whoami` can report the account).

> If you change scopes, you must `npm run build` **and** re-run `npm run auth` so Google re-issues a token with the new scopes.

To run **strictly read-only**, replace the write scopes with their `.readonly` equivalents (e.g. `classroom.coursework.me.readonly`, drop `classroom.topics` and `classroom.announcements`). `drive.readonly` is already read-only. Then rebuild and re-auth.

Config/token location can be overridden with the `CLASSROOM_CONFIG_DIR` env var.

---

## What this server can reach

Worth understanding before you connect it, because the model drives these tools:

- **`drive_fetch_file_content` takes any Drive file id** and reads it with your credentials. It is scoped to `drive.readonly`, which covers *your whole Drive* — not only Classroom attachments — because Classroom attachments are files the app didn't create and `drive.file` cannot see them. A file id that reaches the model from somewhere other than your own course listings will still be fetched. Nothing is written to Drive.
- **Write tools change real state.** `classroom_turn_in_submission` hands work to a teacher; reclaiming it only works while the assignment still allows it. They are annotated `readOnlyHint: false` so a client can prompt before running them.
- **Everything runs as one account** — whichever you picked at the consent screen. Run `classroom_whoami` if you're unsure.

For strictly read-only operation, see [Scopes](#scopes--read-only-mode).

---

## Development

```bash
npm run build       # compile to dist/
npm test            # unit tests (no credentials or network needed)
npm run typecheck   # type-check src + tests
```

The tests stub the Google clients through `setClassroomClient` / `setDriveClient` and drive the tool handlers directly, so the whole suite runs offline.

---

## Troubleshooting

| Symptom | Fix |
|---|---|
| `Not authorized yet` | Run `npm run auth` |
| `Authentication expired` (401) | Run `npm run auth` again |
| `Permission denied` (403) | You're a student calling a teacher-only endpoint, or a scope is missing |
| `OAuth state mismatch` during auth | The redirect didn't come from the consent screen this run opened. Nothing was saved — run `npm run auth` again and use the URL it prints |

TDQS

A4.1/5.0

Scored across 15 tools

Disambiguation5/5

Each list_* tool targets a distinct Classroom resource (courses, topics, coursework, materials, announcements, roster, submissions), and coursework/materials/announcements are explicitly differentiated. Action tools like turn_in, reclaim, and attach have clear, non-overlapping state-transition roles.

Naming Consistency4/5

The set consistently uses a classroom_verb_noun pattern for nearly all tools, with predictable verbs like list, create, turn_in, reclaim, and attach. Minor exceptions are drive_fetch_file_content (different namespace) and classroom_whoami (not verb_noun), but both are still clear and intentional.

Tool Count5/5

Fifteen tools is at the upper end of the ideal range but every tool earns its place: granular listers, a course dump convenience, submission actions, two create operations, a Drive helper, and an auth-check tool. There is no meaningful redundancy in the set.

Completeness3/5

The read-side is strong and the student submission lifecycle is well covered. However, the authoring/management surface is incomplete: there is no way to create coursework or materials, update/delete existing announcements, topics, or coursework, or grade/return submissions as a teacher.

Maintenance

ActivityMaintained
ResponsivenessNo issues