Somtoday (unofficial)

io.github.barzojPublished by GitHub account barzojv0.3.1Updated Oct 29, 2026

Unofficial read-only Somtoday parent portal: timetable, homework, grades, assignments, messages

Overview

AI-generated overview

Unofficial read-only MCP server for the Somtoday parent portal, letting an assistant look up a child's timetable, homework, grades, assignments and messages.

What you can do
  • Look up children, school data, staff and school information pages
  • Read timetables and schedules for a day or date range, including tests, changes and cancellations
  • Read homework, study material, hand-in assignments and their details
  • Review grades: latest results, per-subject detail, yearly overview and school-exam (SE) dossier
  • Check absence registrations, messages, school news, announcements, consents and parent-evening details
  • Read signing requests and their PDFs, and download attachments as extracted text
When to use it
Useful for parents who want to ask an assistant about their own child's school day, homework, upcoming tests or grades without clicking through the portal. It suits quick summaries and planning questions, not anything that changes data in the portal.
Requirements
Runs locally over stdio via npx (npm package somtoday-mcp) and needs Node.js 22 or newer. A one-time interactive login in a terminal is required, using an installed Chrome or Edge browser (or Playwright's Chromium). The session is stored in the macOS Keychain or a session file; optional variables XDG_CONFIG_HOME, SOMTODAY_MCP_CONFIG_DIR and SOMTODAY_MCP_DISABLE_KEYCHAIN change where it is kept. Network access to Somtoday is needed.
Before you install
Handles personal data about children (timetables, grades, absence, messages); keep output on your own devices and use only accounts you are entitled to. The stored session grants access to the portal, so protect it and use logout to remove it. It relies on an undocumented internal API and may break at any time; it is unofficial and not affiliated with Somtoday. It is read-only and never signs, books or sends anything.

Installation

In SourceWeft

  1. Open Somtoday (unofficial) in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

somtoday-mcp

[CI] [Coverage] [npm version] [License: MIT] [Node.js] [ToolSDK MCP Registry]

Read-only MCP server for the Somtoday parent portal. It lets an AI assistant such as Cursor or Claude Desktop look up your child's timetable, homework, and grades from your own parent account.

It runs locally on your computer over stdio. Nothing is sent anywhere except to Somtoday itself.

Disclaimer. This is an unofficial community project. It is not affiliated with, endorsed by, or supported by Somtoday or Topicus. It works by interoperating with the undocumented internal web API that the official parent portal uses, so it may stop working or behave differently at any time without notice. It is intended for use with your own account, only reads data, and is provided as-is, without warranty of any kind (see LICENSE); use it at your own risk and in line with Somtoday's terms of use. "Somtoday" and "Topicus" are trademarks of their respective owners and are used here only to describe what the software works with.

What it does

ToolWhat you get
whoamiYour school label, the linked children with their numeric ids, and which portal sections are visible to you.
lessonsThe timetable for one day, and whether that day is a school holiday. Each lesson has type (ROOSTERTOETS/EXAMEN = test) and uitgevallen when cancelled; homework and test topics come from homework for the same date.
homeworkWhat to do and learn on which day: every study-planner item for a date range (default today + 6 days, max 42), grouped by day, with description, learning goals, time estimate, test type, attachments (links), external links, hand-in window/status and the done tick.
gradesThe most recent results (up to 30) and averages per subject.
assignmentsAll hand-in assignments with window, status (upcoming, to do, waiting for review, approved), late flag, description, attachments and links. status=open keeps the ones still to do.
assignment_detailOne assignment as the parent portal shows it: instruction, files, links, hand-in window and status. Submitted files and teacher reactions are only visible in the student's own session.
study_materialStudy material per subject: lesson material from the planner by date, year attachments by folder (file links), external links, and methods/publisher links. No arguments lists the subjects; vak picks one; all=true fetches every subject.
scheduleTimetable for a date range (default today + 6 days, max 42): time, lesson hour, subject, room, teachers, type (test, exam, parent evening …), lesson notes, changes and cancellations, attachments, holidays.
grades_latestNewest results first with subject, column, description, grade, weight, test type, period, date, remarks and resits; limit (default 50, max 1000) and dossier=examen for SE results.
grades_overviewFull grade overview for a school year: every subject, every result per period, report grades, weights and remarks. schooljaar picks an earlier year.
subject_gradesEverything for one subject: every result column with weights and remarks, column definitions (also not yet graded), composite-test parts, for the progress and exam dossier. No vak lists the subjects.
exam_gradesSchool-exam dossier (PTA/SE): per subject the SE average, every SE result, tests still to come and test-type averages.
absenceAbsence and registrations for the school year or grading period (absent, late, removed, homework/materials not in order) with counts and entries, plus active measures.
messagesMessages, read-only: newest conversations (subject, sender, date, unread, preview; zoek/ongelezen filters) or one full thread with conversatieId. Never marks anything as read.
newsSchool news items (newest first, as text) and the unread count.
announcementsSomtoday-wide announcements shown in the portal.
childrenLinked children with profile, class, school data (mentors, year, programme), current placement and visible portal sections.
school_infoSchool contact data and the school's information pages; paginaId opens one page.
teachersStaff you can message, with the subjects they teach your child.
signing_requestsDigital signing requests (read-only; nothing is signed). Each item has document: {tool: "signing_document", id, available}.
signing_documentThe (signed) PDF of one signing request, as the portal's download button: pass document.id; returns extracted text, max 10 MB. Fetched with your login token, so it is not a fileUrl for download_attachment.
parent_eveningParent-evening details (slots, teachers); finds invitations in your messages (read-only; nothing is booked).
consentsConsents such as use of photos, as set in the portal (read-only).
download_attachmentRead an attachment by fileUrl: https Somtoday hosts only (extend with SOMTODAY_MCP_ATTACHMENT_HOSTS), max 10 MB, no token sent; text from PDF/text/HTML/CSV/JSON.
auth_statusWhether a session is stored, where, and how the last token renewal went. Never returns tokens.
  • lessons takes an optional date (YYYY-MM-DD, Europe/Amsterdam) and defaults to tomorrow. Range tools take date, or from/to.
  • If more than one child is linked to your account, pass leerlingId (the numeric id from whoami).
  • assignments with status=open hides past-due items that expect no digital hand-in (inleveringenVerwacht: 0, e.g. handed in on paper) and reports the count in verborgenZonderInlevering; pass includeNoHandIn=true to see them.
  • assignments merges near-duplicates (same subject, topic, hand-in window and status, e.g. one assignment published to two groups) into one item with the other ids in duplicaatToekenningIds; pass dedupe=false to list them separately.
  • If a section is switched off for your account, the tool says so and does not call that part of the API.

Not included: anything that changes data, such as sending messages, reporting absence, booking parent-evening slots, signing requests, or uploading hand-ins.

Read-only and privacy

  • Tools only send GET requests. Nothing is written, submitted, or marked as read.
  • The server talks only to Somtoday's login and API servers.
  • No telemetry or analytics.
  • Your password is typed only into the Somtoday login page in a browser window. No tool, CLI flag, environment variable, or prompt ever asks for it.
  • Tools never return tokens.

Timetables, homework, and grades are personal data about children. Keep the output on your own devices, use only accounts you are entitled to use, and do not share or republish it. Under the GDPR you are responsible for what you do with data you export.

Install

Requires Node.js 22 or newer (the PDF text extraction used by download_attachment and signing_document does not run on Node 20).

Published on npm as somtoday-mcp, with provenance from this repository's release workflow.

bash
npx -y somtoday-mcp            # start the MCP server (used by your MCP client)npx -y somtoday-mcp login      # sign in, once, in a terminal

Login opens a normal browser window. When Google Chrome (or else Microsoft Edge) is installed, that browser is used, with a fresh temporary profile that is deleted afterwards; it passes Somtoday's Cloudflare "Verify you are human" check more reliably. Only without Chrome/Edge does it fall back to Playwright's bundled Chromium; install that once in that case:

bash
npx playwright install chromium

The window is started without the "controlled by automated software" markers; nothing else about the browser is changed.

From a checkout:

bash
git clone https://github.com/barzoj/somtoday-mcp.gitcd somtoday-mcpnpm installnpm run buildnpx playwright install chromium   # only needed without Chrome/Edgenode dist/cli.js login

MCP client config

Cursor

~/.cursor/mcp.json:

json
{  "mcpServers": {    "somtoday": {      "command": "npx",      "args": ["-y", "somtoday-mcp"]    }  }}

Claude Desktop

claude_desktop_config.json:

json
{  "mcpServers": {    "somtoday": {      "command": "npx",      "args": ["-y", "somtoday-mcp"]    }  }}

From a local checkout

json
{  "mcpServers": {    "somtoday": {      "command": "node",      "args": ["/absolute/path/to/somtoday-mcp/dist/cli.js"]    }  }}

Signing in

Run login in a terminal, not from inside your MCP client:

bash
npx -y somtoday-mcp login
  1. A browser window (your installed Chrome or Edge, else Playwright Chromium) opens on the regular Somtoday login page. Search for your school there, the same way as in the official app.
  2. Sign in as you normally would, including any two-step verification. You have 10 minutes (the Cloudflare check and school search count too).
  3. When the window closes, the session is saved on your computer and the MCP server can use it.

If you know your school's tenant UUID you can skip the school search with npx -y somtoday-mcp login --school-uuid <uuid>.

If a tool is called before you have signed in, or after the saved session stops working, it returns:

run npx somtoday-mcp login in a terminal

Run login again in that case. If Somtoday cannot be reached, tools say so instead of asking you to log in.

Commands

bash
npx -y somtoday-mcp status           # where the session is stored, last renewal result (no tokens)npx -y somtoday-mcp status --check   # also renews the token and calls the API oncenpx -y somtoday-mcp logout           # delete the stored session from this computer

The same diagnostics are available to your MCP client through the auth_status tool.

Several MCP clients (for example two Cursor windows) can share one session: token renewal is serialized with a lock file in the config directory, and each renewal re-reads the stored session first.

Technical details
  • OAuth 2.0 authorization code flow with PKCE (S256), using the public (secret-less) client id and redirect URI of Somtoday's native app. There is no client secret and nothing uses the Somtoday Connect partner API.
  • The login page redirects to a custom somtoday:// URL; Playwright reads the authorization code from that request inside the browser window. No local web server is started.
  • Short-lived access tokens are kept in memory only.
  • The school is chosen on Somtoday's own login page. The school's tenant comes from the token response (somtoday_tenant), and the label shown by whoami and status from the orgname claim (or, failing that, the school data of your account).

Where the session is stored

PlatformLocation
macOSLogin Keychain, service somtoday-mcp. Every write is read back and checked; if that fails, or SOMTODAY_MCP_DISABLE_KEYCHAIN=1 is set, the file below is used
Linux / Windowssession.json with 0600 permissions in $XDG_CONFIG_HOME/somtoday-mcp/ (default ~/.config/somtoday-mcp/)

To sign out, run npx -y somtoday-mcp logout.

Environment variables

VariableEffect
XDG_CONFIG_HOMEBase directory for the file fallback (default ~/.config).
SOMTODAY_MCP_CONFIG_DIRUse this directory instead of $XDG_CONFIG_HOME/somtoday-mcp.
SOMTODAY_MCP_DISABLE_KEYCHAINSet to 1 to skip the macOS Keychain and always use the file.

Logs go to stderr (stdout is reserved for the MCP protocol) and redact token-like values.

Development

bash
npm installnpm run lintnpm run format:checknpm run typechecknpm run buildnpm test

Tests never touch the network: fetch and the keychain are mocked, and requests to Somtoday hosts fail on purpose. See CONTRIBUTING.md for the rules on test data and privacy, and SECURITY.md for reporting vulnerabilities.

ouder-portal.openapi.yaml describes the parts of the parent-portal API this project relies on, as observed from the portal; it is not an official specification.

Manual check against a real account

Not part of CI. Write down HTTP status codes only; never paste tokens, codes, names, or API responses.

  1. node dist/cli.js login and complete the sign-in.
  2. Call whoami, lessons, homework, and grades from your MCP client.
  3. Restart the MCP server and call a tool again, to check that the saved session is picked up.

License

MIT. Not affiliated with Somtoday or Topicus.

Source: README.md at commit 95f929a

Tools

25

whoami

Who am I

Start here: the school label, the numeric leerling ids to pass as leerlingId to other tools, and which parent-portal sections are visible. Use children for full profiles. No tokens.

Takes no parameters.

lessons

Lessons

Timetable for one Amsterdam date, plus whether that date is a holiday. Each lesson has type (ROOSTERTOETS or EXAMEN marks a test in the timetable) and uitgevallen=true when cancelled. Homework and the test topic per lesson are not here: call homework for the same date.

ParametersdateleerlingId

schedule

Schedule

Timetable for a date range, per day: lessons, tests and other appointments with time, lesson hour, subject, room, teachers, type (e.g. ROOSTERTOETS, EXAMEN, OUDERAVOND), lesson notes, changes and cancellations (wijziging, uitgevallen=true, meldingen with real warnings only; the routine 'Inschrijving in orde.' notice is dropped), attachments, and holidays. Every day has items (empty array on a free day). Defaults to today plus 6 days; at most 42 days.

ParameterstodatefromleerlingId

homework

Homework / study planner

What to do and learn on which day: every studiewijzer item (lesson, day and week items) for a date range, grouped by day, with description, learning goals, time estimate, test type, teacher note, attachments (file links), external links, hand-in window and status, and the done tick. Also lists hand-in deadlines per day. Defaults to today plus 6 days; at most 42 days. Every item lists bijlagen (fileUrl, readable with download_attachment) and externeMaterialen; empty means the teacher attached nothing (lesmateriaal=true is only a flag, there is no separate material call).

ParameterstodatefromleerlingId

assignments

Assignments (hand-ins)

All hand-in assignments with their window, status (AANKOMEND, IN_TE_LEVEREN, IN_AFWACHTING, AKKOORD), teLaat (always a boolean: true only for an open hand-in past its deadline), description, attachments and links. status=open keeps upcoming and to-do ones, and by default hides past-due items where no digital hand-in is expected (inleveringenVerwacht 0, e.g. on paper; count in verborgenZonderInlevering); includeNoHandIn=true keeps them. Near-duplicates (same subject, topic, window and status, e.g. published to two groups) are merged by default, with the other ids in duplicaatToekenningIds; dedupe=false lists them separately. Use toekenningId with assignment_detail. Every item lists bijlagen (fileUrl, readable with download_attachment) and externeMaterialen; empty means the teacher attached nothing (lesmateriaal=true is only a flag, there is no separate material call).

ParametersdedupestatusleerlingIdincludeNoHandIn

assignment_detail

Assignment detail

One hand-in assignment as the parent portal shows it: instruction text, learning goals, files (fileUrl) and links, hand-in window, status, late flag and group. Submitted files and teacher reactions are only visible to the student in Somtoday, so they are not returned.

ParametersleerlingIdtoekenningIdrequired

study_material

Study material

Studiemateriaal per subject: lesson material from the study planner (by date), year attachments by folder (file links), external links, and methods/publisher links (book fund). Without arguments: the subjects that have material, plus personal learning products when the school allows it. vak = name, abbreviation or uuid; all=true fetches every subject. Every item lists bijlagen (fileUrl, readable with download_attachment) and externeMaterialen; empty means the teacher attached nothing (lesmateriaal=true is only a flag, there is no separate material call).

ParametersallvakleerlingId

grades

Grades

Quick grade summary: the newest progress-dossier results (capped at 30) plus the average per subject. Use grades_latest for more or exam (SE) results, grades_overview for a whole school year, subject_grades for one subject in depth, and exam_grades for the PTA/SE dossier.

ParametersleerlingId

grades_latest

Latest grades

Newest results first, with subject, column, description, grade, weight, test type, period, date, remarks and resit info. limit defaults to 50 (max 1000, paged). dossier=examen gives school-exam (SE) results. Also the next publication moment when the school uses one. Use this for "what grades came in recently"; use grades for a short summary with averages, subject_grades for all columns of one subject.

ParameterslimitdossierleerlingId

grades_overview

Grade overview

The full grade overview (cijferoverzicht) for a school year: every subject with every result per period, report grades, weights and remarks. Defaults to the current placement; schooljaar like 2025/2026 picks another year. Use this for a whole-year report view or earlier years; use subject_grades for one subject, grades_latest for recent results.

ParametersleerlingIdschooljaar

subject_grades

Subject grades

Everything for one subject: every result column (tests, assignments, period and report averages, SE averages) with weights and remarks, column definitions (also not-yet-graded ones), and the parts of composite tests. Both progress and exam dossier unless dossier is set. Without vak: the list of subjects. Use this to drill into one subject; use grades_overview for all subjects at once.

ParametersvakdossierleerlingId

exam_grades

Exam dossier (SE)

School-exam dossier (PTA/SE) overview: per subject the SE average, every SE result, tests still to come, and test-type averages. Says so when the child has no exam dossier yet. Use this for exam-year progress and upcoming SE tests; use grades_latest with dossier=examen for only the newest SE results.

ParametersexamenjaarleerlingId

absence

Absence and registrations

Registrations for the school year (or current grading period): unexcused and excused absence, late, removed from class, homework not done, materials missing — counts and every entry with date, lesson and remark — plus active measures (e.g. detention).

ParametersperiodeleerlingId

messages

Messages

Somtoday messages (berichten), read-only: newest conversations with subject, sender, date, unread flag and a preview; filter with zoek or ongelezen. Pass conversatieId for the full thread (text, sender, recipients, attachments). Never marks anything as read. Use this for personal messages from teachers and the school; school-wide news is in news, Somtoday-wide notices in announcements.

ParameterszoeklimitongelezenconversatieId

news

School news

News items the school publishes to all parents (nieuwsberichten), newest first, as text, plus the unread count. Use messages for personal conversations and announcements for Somtoday-wide notices from the platform itself.

Parameterslimit

announcements

Announcements

Somtoday-wide announcements (landelijke mededelingen) from the platform itself, such as maintenance notices, with their publication window. Not school news (use news) or personal messages (use messages).

Takes no parameters.

children

Children

Linked children with profile (name, student number, class), school data (school, location, mentor(s), year, programme), current placement, and which portal sections the school shows. Use whoami when you only need leerling ids.

Takes no parameters.

school_info

School information

School contact data per child and the school's published information pages. Pass paginaId for one page with its topics and documents. Use teachers for staff and children for mentors.

ParameterspaginaId

teachers

Teachers

Teachers and other staff you can message in Somtoday, with the subjects they teach your child. Use children for the mentor(s) and school_info for general school contact data.

Takes no parameters.

signing_requests

Signing requests

Digital signing requests (ondertekenverzoeken) waiting for you or done. Each item has document {tool:'signing_document', id, available}: pass id to signing_document to read the (signed) PDF. Read-only; nothing is signed.

Takes no parameters.

signing_document

Signing document

Read the document (PDF) of one signing request, as the portal's download button does: pass document.id from signing_requests. Returns extracted text (max 10 MB). The document needs your login, so it is not a fileUrl for download_attachment. Usually available once signed; not for requests still to sign, withdrawn or expired.

Parametersidrequired

parent_evening

Parent evening

Parent-evening (ouderavond) details: invitation, time slots and chosen teachers. Without id, finds invitations linked in your messages. Read-only; nothing is booked.

Parametersid

consents

Consents

Consents (toestemmingen) as set in the portal: each consent item (e.g. use of photos) with the answer recorded in the portal. Read-only; answers cannot be changed here.

Takes no parameters.

download_attachment

Download attachment

Read an attachment (fileUrl from homework, assignments, study material or messages). Only https Somtoday file hosts; max 10 MB; returns extracted text for PDF/text/HTML/CSV/JSON, metadata otherwise.

Parametersurlrequired

auth_status

Auth status

Whether a Somtoday session is stored, where (keychain or file), and the outcome of the last token renewal. Never returns tokens. Set check=true to renew the token and call the API once.

Parameterscheck

Version history

1
  1. v0.3.1LatestOct 23, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts
  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts