Files
Schulcloud-MCP/local-instance/scripts/mcp-env.sh
MechaCat02 3a168e37e5 local-instance: simulate a teacher, and run the files-storage consumer
`scripts/simulate-teacher.mjs` creates, edits and deletes what teachers
create — course, room, topic, task, board, columns, cards, rich text,
link, Etherpad pad, folder, files — so the MCP server can be exercised
against content the real account has never held. It is the only thing
here that writes to a Schulcloud and refuses any non-localhost address.
`scripts/mcp-env.sh` points the server and CLI at the instance.

Two gaps it exposed in the stack itself:

The files-storage AMQP consumer is a separate entrypoint, and we were
running only the HTTP one. Nothing was bound to the `files-storage`
exchange, so `TaskService.delete` — which awaits deleteFilesOfParent
over AMQP before touching the task — hung until the request timeout.
Deleting any task or topic answered 408 with the entity still there.

The demo data is dated 2017-2018 and the v3 endpoints filter on those
dates, so a student saw no tasks at all. seed.sh now brings courses and
homework into the present, which is the difference between a fixture
that exercises the student-facing surface and one that looks empty.

Teams turn out to be uncreatable through the API (the legacy service
registers no `create`, v3 has no route), and a new board is unpublished
and 403s for students, so the simulation adopts a seeded team and leaves
one board a draft on purpose.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-13 15:40:46 +02:00

31 lines
1.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Mint a session on the local instance and print the environment the MCP server
# and CLI expect, so they can be pointed at it instead of the live Schulcloud.
#
# eval "$(./scripts/mcp-env.sh)" # as the demo student
# eval "$(./scripts/mcp-env.sh klara.fall@schul-cloud.org Schulcloud1\!)"
#
# Nothing is written to the repo: the output contains a live session token, and
# a throwaway instance is still no reason to start committing those.
set -euo pipefail
# `localhost`, not `127.0.0.1`: it must match SC_DOMAIN, because urls the server
# hands back (Etherpad pads, for one) are built from it, and the client refuses
# to follow a url onto a different host rather than leak a session cookie there.
URL=${LOCAL_SC_URL:-http://localhost:4400}
USER=${1:-demo-schueler@schul-cloud.org}
PASS=${2:-schulcloud}
token=$(curl -fsS -X POST "$URL/api/v3/authentication/local" \
-H 'Content-Type: application/json' \
-d "$(printf '{"username":%s,"password":%s}' \
"$(printf '%s' "$USER" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')" \
"$(printf '%s' "$PASS" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')")" \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["accessToken"])')
cat <<ENV
export TSC_URL=$URL
export TSC_JWT_COOKIE=$token
export MCP_AUTH_TOKEN=local-instance-token
ENV