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.

io.github.barzojPublished by GitHub account barzojv0.3.1Updated Oct 29, 2026
Unofficial read-only Somtoday parent portal: timetable, homework, grades, assignments, messages
Unofficial read-only MCP server for the Somtoday parent portal, letting an assistant look up a child's timetable, homework, grades, assignments and messages.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Follow the launch instructions in the repository.
[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.
lessons takes an optional date (YYYY-MM-DD, Europe/Amsterdam) and defaults to tomorrow. Range tools take date, or from/to.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.Not included: anything that changes data, such as sending messages, reporting absence, booking parent-evening slots, signing requests, or uploading hand-ins.
GET requests. Nothing is written, submitted, or marked as read.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.
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.
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:
The window is started without the "controlled by automated software" markers; nothing else about the browser is changed.
From a checkout:
~/.cursor/mcp.json:
claude_desktop_config.json:
Run login in a terminal, not from inside your MCP client:
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.
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.
somtoday:// URL; Playwright reads the authorization code from that request inside the browser window. No local web server is started.somtoday_tenant), and the label shown by whoami and status from the orgname claim (or, failing that, the school data of your account).To sign out, run npx -y somtoday-mcp logout.
Logs go to stderr (stdout is reserved for the MCP protocol) and redact token-like values.
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.
Not part of CI. Write down HTTP status codes only; never paste tokens, codes, names, or API responses.
node dist/cli.js login and complete the sign-in.whoami, lessons, homework, and grades from your MCP client.MIT. Not affiliated with Somtoday or Topicus.
Source: README.md at commit 95f929a
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
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.
dateleerlingIdSchedule
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.
todatefromleerlingIdHomework / 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).
todatefromleerlingIdAssignments (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).
dedupestatusleerlingIdincludeNoHandInAssignment 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.
leerlingIdtoekenningIdrequiredStudy 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).
allvakleerlingIdGrades
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.
leerlingIdLatest 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.
limitdossierleerlingIdGrade 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.
leerlingIdschooljaarSubject 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.
vakdossierleerlingIdExam 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.
examenjaarleerlingIdAbsence 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).
periodeleerlingIdMessages
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.
zoeklimitongelezenconversatieIdSchool 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.
limitAnnouncements
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
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 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.
paginaIdTeachers
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
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
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.
idrequiredParent evening
Parent-evening (ouderavond) details: invitation, time slots and chosen teachers. Without id, finds invitations linked in your messages. Read-only; nothing is booked.
idConsents
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
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.
urlrequiredAuth 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.
check90% 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.
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
npx -y somtoday-mcp # start the MCP server (used by your MCP client)npx -y somtoday-mcp login # sign in, once, in a terminalnpx playwright install chromiumgit 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{ "mcpServers": { "somtoday": { "command": "npx", "args": ["-y", "somtoday-mcp"] } }}{ "mcpServers": { "somtoday": { "command": "npx", "args": ["-y", "somtoday-mcp"] } }}{ "mcpServers": { "somtoday": { "command": "node", "args": ["/absolute/path/to/somtoday-mcp/dist/cli.js"] } }}npx -y somtoday-mcp loginnpx -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 computernpm installnpm run lintnpm run format:checknpm run typechecknpm run buildnpm test