Somtoday (unofficial)

io.github.barzoj由 GitHub 账号 barzoj 发布v0.3.1更新于 Oct 29, 2026

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

已验证STDIO仅桌面效率与工作流沟通与协作

概览

AI 生成的概览

非官方的 Somtoday 家长门户只读 MCP 服务器,让助手查询孩子的课表、作业、成绩、作业提交与消息。

可以做什么
  • 查询关联孩子、学校资料、教职工与学校信息页面
  • 读取单日或日期范围的课表,含测验、变更与停课
  • 读取作业、学习资料、需提交的作业及其详情
  • 查看成绩:最新结果、单科详情、学年总览与学校考试(SE)档案
  • 查看缺勤记录、消息、学校新闻、公告、同意事项与家长会信息
  • 读取签字请求及其 PDF,并将附件下载为提取文本
适用场景
适合家长让助手了解自己孩子的在校日程、作业、即将到来的测验或成绩,无需逐页浏览门户。适用于快速汇总与安排类问题,不涉及在门户中修改任何数据。
运行要求
通过 npx(npm 包 somtoday-mcp)以 stdio 在本机运行,需要 Node.js 22 或更高版本。需在终端完成一次交互式登录,使用已安装的 Chrome 或 Edge(否则用 Playwright 的 Chromium)。会话保存在 macOS 钥匙串或会话文件中;可选变量 XDG_CONFIG_HOME、SOMTODAY_MCP_CONFIG_DIR 和 SOMTODAY_MCP_DISABLE_KEYCHAIN 可改变保存位置。需要能访问 Somtoday 的网络。
安装前请注意
涉及儿童的个人数据(课表、成绩、缺勤、消息),请仅在本机保存输出,并使用你有权使用的账号。保存的会话可访问门户,需妥善保护,可用 logout 删除。它依赖未公开的内部 API,可能随时失效;属非官方项目,与 Somtoday 无关联。它只读,不会签署、预约或发送任何内容。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Somtoday (unofficial),将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

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.

来源:README.md,提交 95f929a

工具

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.

无需输入参数。

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.

输入参数dateleerlingId

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.

输入参数todatefromleerlingId

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).

输入参数todatefromleerlingId

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).

输入参数dedupestatusleerlingIdincludeNoHandIn

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.

输入参数leerlingIdtoekenningId必填

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).

输入参数allvakleerlingId

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.

输入参数leerlingId

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.

输入参数limitdossierleerlingId

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.

输入参数leerlingIdschooljaar

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.

输入参数vakdossierleerlingId

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.

输入参数examenjaarleerlingId

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).

输入参数periodeleerlingId

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.

输入参数zoeklimitongelezenconversatieId

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.

输入参数limit

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).

无需输入参数。

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.

无需输入参数。

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.

输入参数paginaId

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.

无需输入参数。

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.

无需输入参数。

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.

输入参数id必填

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.

输入参数id

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.

无需输入参数。

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.

输入参数url必填

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.

输入参数check

版本历史

1
  1. v0.3.1最新Oct 23, 2026

评分

已满足适用检查项的 90%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分
  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分