Skip to main content
Glama
README.md
# Google Classroom MCP (local)

This MCP server exposes multiple tools for read + write:
- `classroom_get_user_enrollments`
- `classroom_get_course`
- `classroom_list_courses`
- `classroom_create_course`
- `classroom_update_course`
- `classroom_set_course_state`
- `classroom_archive_course`
- `classroom_activate_course`
- `classroom_delete_course`
- `classroom_list_course_students`
- `classroom_list_course_teachers`
- `classroom_add_teacher_to_course`
- `classroom_remove_teacher_from_course`
- `classroom_add_student_to_course`
- `classroom_remove_student_from_course`
- `classroom_list_invitations`
- `classroom_get_invitation`
- `classroom_create_invitation`
- `classroom_delete_invitation`
- `classroom_accept_invitation`
- `classroom_list_course_topics`
- `classroom_create_topic`
- `classroom_create_announcement`
- `classroom_list_coursework_materials`
- `classroom_create_coursework_material`
- `classroom_list_coursework`
- `classroom_create_assignment`
- `classroom_clone_course`
- `classroom_list_student_submissions`
- `classroom_set_draft_grade`
- `classroom_set_assigned_grade`
- `classroom_turn_in_submission`
- `classroom_reclaim_submission`
- `classroom_return_submission`

## 1) Google Workspace setup

1. Create (or choose) a Google Cloud project.
2. Enable **Google Classroom API**.
3. Create a **Service Account** and download its JSON key.
4. Enable **Domain-wide delegation** on that service account.
5. In Google Admin Console, go to `Security > API controls > Domain-wide delegation` and add:
   - Client ID: service account client ID
   - OAuth scopes (comma-separated):
     - `https://www.googleapis.com/auth/classroom.courses.readonly`
     - `https://www.googleapis.com/auth/classroom.courses`
     - `https://www.googleapis.com/auth/classroom.rosters.readonly`
     - `https://www.googleapis.com/auth/classroom.rosters`
     - `https://www.googleapis.com/auth/classroom.profile.emails`
     - `https://www.googleapis.com/auth/classroom.topics.readonly`
     - `https://www.googleapis.com/auth/classroom.topics`
     - `https://www.googleapis.com/auth/classroom.announcements`
     - `https://www.googleapis.com/auth/classroom.coursework.students.readonly`
     - `https://www.googleapis.com/auth/classroom.coursework.students`
     - `https://www.googleapis.com/auth/classroom.coursework.me`
     - `https://www.googleapis.com/auth/classroom.courseworkmaterials.readonly`
     - `https://www.googleapis.com/auth/classroom.courseworkmaterials`
6. Ensure the delegated admin user can read Classroom data in your domain.

## 2) Local install

```bash
cd /home/carlos/classroom-mcp
bash setup.sh
cp .env.example .env
# edit .env
```

Optional policy in `.env`:

```bash
CLASSROOM_REQUIRED_TEACHERS=osvalin15@certificacionmontessori.com,online@asociacionmontessori.mx
CLASSROOM_OBSOLETE_TEACHERS=presidencia@asociacionmontessori.mx
```

When set, these teachers are auto-added for:
- `classroom_create_course`
- `classroom_clone_course`

Obsolete filter behavior:
- `classroom_list_courses` and `classroom_get_user_enrollments` exclude courses that include any teacher from `CLASSROOM_OBSOLETE_TEACHERS`.
- If `CLASSROOM_OBSOLETE_TEACHERS` is not set, default exclusion is `presidencia@asociacionmontessori.mx`.
- Set `CLASSROOM_OBSOLETE_TEACHERS=` (empty) to disable this filter.

## 3) Register in Codex

```bash
codex mcp add classroom -- /home/carlos/classroom-mcp/run.sh
codex mcp list
```

## 4) Example prompt in Codex

```text
En qué materias está registrado el usuario guiarodrigo@asociacionmontessori.mx?
```

## 5) Smoke test (portable)

Run the full write-path smoke test with automatic cleanup:

```bash
cd /home/carlos/classroom-mcp
./smoke_test.sh
```

You can override inputs with flags:

```bash
./smoke_test.sh \
  --teacher-email carlos@certificacionmontessori.com \
  --student-email carlos@asociacionmontessori.com.mx \
  --course-id 765463029199
```

Or set defaults in `.env`:
- `SMOKE_TEST_TEACHER_EMAIL`
- `SMOKE_TEST_STUDENT_EMAIL`
- `SMOKE_TEST_COURSE_ID`

Keep generated artifacts (no cleanup) only when debugging:

```bash
./smoke_test.sh --keep-artifacts
```

## 6) Admin smoke test (course lifecycle + invitations)

This covers the newer admin tools:
- create/update/archive/activate/delete course
- add/remove teacher
- create/get/list/accept/delete invitation

```bash
cd /home/carlos/classroom-mcp
./admin_smoke_test.sh
```

With explicit inputs:

```bash
./admin_smoke_test.sh \
  --admin-email admin@asociacionmontessori.com.mx \
  --teacher-email carlos@certificacionmontessori.com \
  --student-email carlos@asociacionmontessori.com.mx
```

Defaults can live in `.env`:
- `ADMIN_SMOKE_ADMIN_EMAIL`
- `ADMIN_SMOKE_TEACHER_EMAIL`
- `ADMIN_SMOKE_STUDENT_EMAIL`

## 7) Clone course example (MCP)

Use the new tool to clone structure + content safely as drafts:

```text
classroom_clone_course(
  source_course_id="844288618274",
  new_course_name="Copia de F12 - Lenguaje",
  teacher_emails=["carlos@certificacionmontessori.com"],
  student_emails=["carlos@asociacionmontessori.com.mx"],
  copy_topics=true,
  copy_coursework=true,
  copy_coursework_materials=true,
  force_draft_for_created_work=true
)
```

## Notes

- If the user exists outside your Workspace domain, Google may return 403/404.
- If you need archived courses too, ask with `course_state="ARCHIVED"`.
- `acting_user_email` lets you impersonate a teacher/admin for operations that require role-specific permissions.
- `classroom_create_announcement` does not support real Classroom topic binding; if `topic_id` is sent, it is appended as text marker.
- `classroom_create_course` defaults to `PROVISIONED` for safer setup before going live.
- `classroom_create_course` defaults `ownerId` to `acting_user_email` (or `GOOGLE_WORKSPACE_ADMIN_EMAIL`) when not provided.
- `classroom_delete_course` permanently deletes the course; prefer `classroom_archive_course` when in doubt.
- `classroom_clone_course` creates a new course and can copy topics, coursework, and course work materials with optional teacher/student enrollment.
- `classroom_clone_course` defaults `force_draft_for_created_work=true` to avoid publishing cloned content unexpectedly.