Skip to main content
Glama
NSK-394

SchoolBridge

by NSK-394
README.md
# SchoolBridge

SchoolBridge is a small MCP (Model Context Protocol) server that lets an AI
agent safely query and act on school data — attendance, fees, student
records — without ever bypassing role-based access control. It exists to
answer one question: *can an AI agent be given access to a school's data
without that access becoming a liability?*

Every single read or write request, from any role, goes through one shared
authorization function. If that function doesn't explicitly allow a
request, it is denied — there is no default-allow path anywhere in this
project. Every request, allowed or denied, is written to an audit log.
Write actions (like recording a fee payment) never happen in a single
step: an agent can only *propose* a write, and a school admin must
separately *confirm* it before anything is actually saved.

This is a proof-of-concept built with 100% synthetic, fictional data. It
does not connect to any real school, ERP vendor, or student records.

## Who is who (roles)

| Role | Can see |
|---|---|
| Admin | Everything in their own school; the only role that can confirm write actions |
| Teacher | Only the classes they're assigned to teach |
| Parent | Only their own child's record (never a whole class) |
| Student | Only their own record, read-only |

## Prerequisites

- Python 3.10 or newer installed on your machine.
- No internet connection or API keys are needed — everything runs locally
  against a local SQLite database file.

To check you have Python installed, open a terminal and run:

```
python --version
```

If that fails, try `python3 --version` or `py --version` instead — use
whichever one works for the rest of these commands.

## Setup

Open a terminal in this folder (`school-erp-mcp/`) and run the following,
one line at a time.

**Windows (PowerShell or Command Prompt):**

```
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
```

**macOS / Linux:**

```
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

You'll know it worked if your terminal prompt now starts with `(.venv)`.

## Create the demo data

This generates a local database file (`data/school_erp.db`) with two fake
schools, fake classes, fake students, and fake staff/parent accounts. No
real people or real schools are involved.

```
python -m data.seed
```

You should see output like:

```
Seeded 2 schools, 8 students, 22 requesters, 0 pending actions.
```

If you ever want to start over with a completely fresh database, delete
`data/school_erp.db` and run this command again.

## Run the tests

This proves the access-control rules actually work — every role, every
"who can see what" boundary, and the write-approval flow.

```
pytest tests/ -v
```

All tests should show `PASSED`. If you see any `FAILED`, something is
broken and should not be trusted — please report it rather than assuming
it's fine.

## Try it yourself

For a full, copy-pasteable walkthrough — an allowed query, a denied
query, a complete write-approval flow, and the resulting audit log — see
[docs/demo.md](docs/demo.md).

## Run the actual MCP server

Once you're happy with the demo, the server itself is started with:

```
python server.py
```

This starts the MCP server over stdio, ready for an MCP-compatible AI
client (e.g. Claude Desktop, or any MCP client) to connect to it and call
its tools (`get_attendance`, `get_fee_status`, `get_student_summary`,
`flag_defaulters`, `get_recent_audit_log`, `propose_fee_payment`,
`propose_attendance_update`, `confirm_action`).

## How access control works, in plain terms

Every tool call goes through one function: `authorize()`
(`core/access_control.py`). It checks, in this exact order:

1. Does this requester_id actually exist? If not, deny.
2. Is the thing they're asking about (a student, a class) in their own
   school? If it's in a different school, deny — no exceptions.
3. Are they an admin? If so, allow (within their own school).
4. Are they a teacher, and is this their class (or a student in their
   class)? If so, allow.
5. Are they a parent, and is this specifically their own child (never a
   whole class)? If so, allow — otherwise deny.
6. Are they a student, and is this specifically their own record,
   read-only? If so, allow — otherwise deny.
7. Anything else: deny.

No tool ever implements its own version of this check — they all call the
exact same function, so there's exactly one place in the whole codebase
where "who can see what" is decided.

## How the audit log works

Every single request — allowed or denied — is appended to
`logs/audit.jsonl` as one line of JSON: who asked, what role they have,
what they asked for, and whether it was allowed. It deliberately never
records the actual sensitive data (fee amounts, attendance numbers) —
only that the request happened. Only admins can read this log
(`get_recent_audit_log`), and only for their own school.

## How write actions (like recording a payment) work

An AI agent can never go straight from "record this payment" to it being
saved. It's always two separate steps:

1. **Propose** — `propose_fee_payment` or `propose_attendance_update`
   creates a pending request and returns an id. Nothing is saved yet.
2. **Confirm** — a school admin calls `confirm_action` with that id. Only
   then is the change actually applied. The confirmation re-checks that
   the confirming admin is still allowed to approve this — it does not
   just trust that the original request was fine.

Pending requests that aren't confirmed within 15 minutes expire and can
no longer be confirmed.

## What this project deliberately does not do (v1 scope)

- It does not connect to any real school ERP (Fedena, Entab, etc.) — that
  would be a future integration layer on top of this.
- It has no web dashboard or user interface — it's an API layer for AI
  agents, accessed via MCP.
- It does not handle billing, multi-school onboarding, or real payment
  processing.
- All data is synthetic. There is no real student, parent, or staff
  information anywhere in this repository.