fskintra-mcp
Provides an add-on for Home Assistant, allowing Home Assistant's Model Context Protocol integration to connect to the server via SSE and answer questions about school data out loud through Assist.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@fskintra-mcpShow me today's news and messages for my child."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
fskintra-mcp
An MCP server for ForældreIntra (SkoleIntra) — logs in as a parent and exposes news, messages, weekly plans, homework, documents, photos, contacts and sign-ups as tools an AI agent can call.
What this is — and what it is not:
fskintra-mcp is a server that sits between an MCP client (an LLM) and
ForældreIntra. It is an interface, not much more. The LLM is not part of this
project. You pick the client yourself — Claude Code, Claude Desktop, ChatGPT,
Cursor, Ollama, LM Studio — and it runs wherever it runs: in Anthropic's or
OpenAI's cloud, or locally if you use Ollama or similar.
So this project is not a guarantee that your children's data stays local.
Whether it does depends entirely on which client you connect. That is your
call, not something fskintra-mcp can promise.
⚠️ Use it with care
A hobby experiment, no guarantees. It handles your ForældreIntra password and your children's school data — read the code (or have a developer friend read it) before you point an LLM at it. At your own risk.
⚠️ It's the client that sees the data — not the server
The server runs locally and forwards nothing on its own. But the MCP client you connect — Claude, ChatGPT, any other cloud LLM — gets everything it reads sent on to the provider (Anthropic, OpenAI, …) so it can answer you. It is not "all local" just because the server is. That is how MCP works: the client reasons, the server fetches.
Where it goes
ForældreIntra username and password
Stays local — macOS Keychain or an AES-256-GCM encrypted file. Used only to log in to ForældreIntra.
The data itself (messages, weekly plans, children's names, photos, …)
Goes to whichever MCP client you choose. Cloud LLM → that provider's servers (typically the US). Local LLM → stays local.
Want it 100 % local? Use a local LLM as the client: Ollama, LM Studio, llama.cpp. They all speak MCP and run on your own hardware.
Unofficial and third-party. Not affiliated with itslearning — see Privacy & legal.
Where this comes from
Two projects, two different debts:
svalgaard/fskintra — a long-running Python tool that turns ForældreIntra into email. None of its code is reused (it is Python 2 on
mechanize), but it is the only written-down description of ForældreIntra's login flow, URL map and DOM selectors that exists. That reverse-engineering is what this project stands on.Casperjuel/aula-mcp — the same problem solved for Aula. The architecture here is deliberately borrowed from it: layered packages, encrypted credential store, wire-tracing with redaction, a
discover-first tool surface, and adoctorcommand.docs/architecture.mdsays which parts transferred unchanged and which ForældreIntra forced a different answer to.
Related MCP server: aula-mcp
Quick start
bun install
bun run fskintra login
bun run fskintra doctor # does anything actually parse?Then wire it into an agent — see examples/claude-config:
claude mcp add foraldreintra -- bun $PWD/packages/mcp-server/src/server-stdio.tsOnly ordinary ForældreIntra login ("alm login") is supported. If your school redirects to UNI-Login, the client stops with an explicit error rather than half-working.
Start with doctor
$ bun run fskintra doctor
• Store backend: macOS Keychain
✓ Logged in to minskole.skoleintra.dk as emil
• Message UI: conversations
• Children: Andrea 3A, Bertil 6B
──────────────────────────────────────── Andrea 3A
✓ news child=Andrea 3A reminders=1 news=6 (412ms)
✓ messages 12 item(s) (233ms)
! weekplans ForældreIntra says "ikke autoriseret".
✓ homework 2 item(s) (890ms)
✓ documents 14 item(s) (301ms)Three outcomes, and the difference between the last two is the point:
Mark | Meaning |
✓ | Parsed |
! | Your school does not have this module |
✗ | A parser bug — please file it |
Add --debug for a sanitised wire transcript, and --dump <dir> to save what
each section parsed.
Tools
Agents should call foraldreintra.discover once and work from the manifest:
it returns the children, which sections this school actually has, and which
message UI it runs.
Tool | What it does |
| Children, per-section availability, capability→tool map |
| Front-page news with author, recipients, date, attachments; comments optional |
| Conversation list with thread/message ids |
| Every message in one conversation |
| Weekly plans, per day |
| Homework grouped by due date |
| Class documents including sub-folders |
| Photo albums and image URLs |
| Contact cards for the class |
| Open sign-ups for conversations and events |
| Saves an attachment to a local path |
| Fresh login, discarding the cached session |
Behind flags: foraldreintra.messages.mark_read (FSKINTRA_MCP_WRITE=1) and
foraldreintra.raw_request (FSKINTRA_MCP_RAW=1). The server is read-only
without them.
CLI
fskintra login [--hostname H] [--username U] [--debug] [--no-store-password]
fskintra status | whoami | logout
fskintra doctor [--json] [--debug] [--dump DIR]
fskintra discover
fskintra fetch <section> [--child NAME] [--limit N] [--comments]
fskintra thread <message-id> [--thread THREAD_ID]
fskintra log [--last N]
fskintra transcript list | view <file> | prune [--keep N]How it fits together
fskintra-auth → fskintra-client → mcp-server
↑
apps/clipackages/fskintra-auth— cookie-jar HTTP client with manual redirect walking, the login state machine, wire tracing, and the encrypted session store (Keychain on macOS, AES-256-GCM file elsewhere).packages/fskintra-client— one module per section, plus the section-availability probe. Every parser has a pureDoc → datafunction.packages/mcp-server— tools,discover, and both transports.apps/cli—fskintra.
Three decisions worth knowing before you read the code:
Redirects are followed by hand. fetch doesn't expose Set-Cookie from
intermediate hops, and the SSO relay sets cookies there.
The stored session includes your password. ForældreIntra has no refresh
token; replaying the login form is the only way to renew a dead session. That is
why the store is encrypted. --no-store-password opts out, at the cost of
needing you present at every expiry.
"Unavailable" and "empty" are different types. A school without homework answers "ikke autoriseret". An agent handed an empty array tells a parent "no homework this week", which would be false.
Full reasoning in docs/architecture.md.
Configuration
Variable | Effect |
| Config dir (default |
| Encryption key (64 hex chars) or passphrase for the file backend |
| Use the encrypted file instead of the macOS Keychain |
| Verbose logs (stderr under stdio) |
| Register write tools |
| Register the raw page-fetch escape hatch |
| Submit the "Bekræft kontaktoplysninger" form automatically |
| HTTP server bind (default |
| Permit a non-loopback bind (refused otherwise) |
| Credentials for headless installs, instead of |
Home Assistant
There is an add-on: homeassistant-addon/.
Point HA's Model Context Protocol integration at
http://homeassistant.local:7979/sse and Assist can answer questions about
school out loud.
Known limits
Nothing here has run against a live ForældreIntra yet. Every selector is ported from a codebase that froze years ago.
fskintra doctoris the first move.UNI-Login is not supported.
Read-only. No sending messages, no signing up for events.
The old message UI is the less-tested of the two.
Selectors are a moving target. Sections fail independently; one broken parser doesn't take the others down.
Development
bun test # 91 tests, no network
bun run typecheck
bun run lintSee CONTRIBUTING.md — particularly the part about keeping
"unavailable" and "broken" apart when you touch a parser.
Privacy & legal
Your ForældreIntra username and password stay on your machine. The HTTP server
binds to 127.0.0.1 by default and refuses a non-loopback bind unless you set
FSKINTRA_MCP_ALLOW_REMOTE=1. No telemetry. The wire trace is opt-in
(--debug), and every known-secret field is redacted before anything is written
to disk.
The data itself — messages, weekly plans, children's names, photos — is passed on to whichever MCP client you connect. Where that client sends it is the client's business, not the server's; see the disclaimer at the top.
Use this for your own children's data — log in as yourself with your own ForældreIntra account. Do not use it to reach anyone else's account.
Disclaimer. This project is not affiliated with, endorsed by or sponsored by itslearning AS, UNI-C, or any Danish school or municipality. SkoleIntra and ForældreIntra are trademarks of their respective owners; the names are used here solely to identify what this software talks to. Provided "as is", without warranty of any kind — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
Hosted MCP server for AI agent identity, permissions, verification, and reusable proof.
1MCP server for e-mail testing: create disposable inboxes, wait for delivery, and extract e-mail content or links - all from your AI agent or test automation workflow. Get a free API key on https://app.zyntra.app/
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceMCP server for the Omnivox platform used by Quebec CEGEPs. Enables AI agents to access course schedules, grades, MIO messages, evaluations, and documents from Omnivox-based institutions.4MIT
- AlicenseNot gradedqualityAmaintenanceThis server enables MCP clients (LLMs) to access data from the Danish school platform Aula, such as messages, schedules, and child profiles, by authenticating via MitID and running locally.744MIT
- AlicenseNot gradedqualityCmaintenanceMCP server that gives Claude Desktop access to school data from Studie+ (Danish school platform), enabling queries about schedules, homework, assignments, and files directly in chat.MIT
- FlicenseAqualityCmaintenanceA local MCP server for reading ParentSquare data (feeds, calendar, messages, directory, groups, and more) using undocumented internal APIs. It enables Claude, Cursor, and other MCP clients to access your ParentSquare account via stdio.231-