@jamestesting888/tum-mcp 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/NOTICE +2 -4
- package/README.md +162 -59
- package/docs/development.md +113 -92
- package/docs/setup.md +83 -31
- package/docs/study.md +325 -0
- package/docs/tum-mcp.md +136 -163
- package/npm/backend/manifest.json +3 -3
- package/npm/backend/requirements.txt +22 -18
- package/npm/backend/tum_mcp-0.6.1-py3-none-any.whl +0 -0
- package/npm/lock.mjs +43 -0
- package/npm/npm-command.mjs +96 -0
- package/npm/package-manager.mjs +109 -0
- package/npm/runtime.mjs +177 -61
- package/npm/tum-mcp.mjs +49 -12
- package/package.json +53 -10
- package/npm/backend/tum_moodle_integration-0.5.0-py3-none-any.whl +0 -0
package/docs/tum-mcp.md
CHANGED
|
@@ -1,52 +1,50 @@
|
|
|
1
1
|
# TUM MCP guide
|
|
2
2
|
|
|
3
3
|
Package: `@jamestesting888/tum-mcp`, CLI: `tum-mcp`, backend: Python 3.13.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Windows client setup. The package supports campus reads and local assignment
|
|
7
|
-
assistance; remote-action tools remain disabled.
|
|
4
|
+
Development version **0.6.1 (unreleased)** adds npm package management to the
|
|
5
|
+
read-only course retrieval and five local study workflows in 0.6.0.
|
|
8
6
|
|
|
9
7
|
## Current capabilities
|
|
10
8
|
|
|
11
|
-
The
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
public discovery. Provider routes were checked against that Artemis revision.
|
|
9
|
+
The sixteen `moodle_*` tools provide materials, announcements, forums and
|
|
10
|
+
explicitly scoped private-record reads. Artemis adds
|
|
11
|
+
available-course metadata, lectures and learning units, student PDF attachments,
|
|
12
|
+
released non-quiz statements and permitted exact-commit feedback. Zulip provides
|
|
13
|
+
scoped channel/topic search and cited discussion reads.
|
|
14
|
+
|
|
15
|
+
Website access is read-only. There are no public exercise workspace, test-run,
|
|
16
|
+
submission, start, deployment, rebuild or push workflows.
|
|
17
|
+
Local downloads, source inventories, study-site builds and checkpoint storage
|
|
18
|
+
are local operations; they do not post, submit or mark campus content as read.
|
|
19
|
+
|
|
20
|
+
Artemis lecture reads use the student overview/detail endpoints, verify the
|
|
21
|
+
selected course and omit unreleased units and personal completion records.
|
|
22
|
+
`artemis_get_attachment` retrieves a bounded page range from the student PDF,
|
|
23
|
+
which excludes hidden slides, and optionally saves that copy locally. Original
|
|
24
|
+
staff links are never fetched. Video/online links remain cited references;
|
|
25
|
+
unsupported or external content is reported as a retrieval gap.
|
|
26
|
+
|
|
27
|
+
Lecture routes were checked against the
|
|
28
|
+
[Artemis source](https://github.com/ls1intum/Artemis/blob/88824427f7ea38512606824c58b8858e539eb2eb/src/main/java/de/tum/cit/aet/artemis/lecture/web/LectureResource.java)
|
|
29
|
+
and the
|
|
30
|
+
[student file boundary](https://github.com/ls1intum/Artemis/blob/88824427f7ea38512606824c58b8858e539eb2eb/src/main/java/de/tum/cit/aet/artemis/core/web/FileResource.java).
|
|
31
|
+
Synthetic fixtures are the default. Live checks remain private and use explicit scopes.
|
|
35
32
|
|
|
36
33
|
## Build and test the local package
|
|
37
34
|
|
|
38
|
-
For normal installation, use `npm install --global @jamestesting888/tum-mcp@
|
|
35
|
+
For normal installation, use `npm install --global @jamestesting888/tum-mcp@latest`
|
|
39
36
|
and `tum-mcp setup --client codex`. The following commands are for maintainers.
|
|
40
37
|
|
|
41
38
|
```sh
|
|
42
39
|
uv sync --locked
|
|
43
|
-
uv run ruff check src tests
|
|
44
|
-
uv run ruff format --check src tests
|
|
40
|
+
uv run ruff check src tests scripts
|
|
41
|
+
uv run ruff format --check src tests scripts
|
|
45
42
|
uv run pytest -q -m 'not live'
|
|
46
43
|
node npm/build.mjs
|
|
47
44
|
npm test
|
|
48
45
|
npm pack --ignore-scripts --pack-destination dist
|
|
49
|
-
npm run test:consumer
|
|
46
|
+
npm run test:consumer
|
|
47
|
+
npm run test:upgrade
|
|
50
48
|
```
|
|
51
49
|
|
|
52
50
|
The npm artifact has an explicit file allowlist, a bundled backend wheel,
|
|
@@ -69,20 +67,19 @@ and Python 3.13.15; an existing matching uv, including the verified cached downl
|
|
|
69
67
|
is reused. Source checkouts and system
|
|
70
68
|
Python are unnecessary for consumers. Supported bootstrap targets are macOS
|
|
71
69
|
arm64/x64, Windows arm64/x64, and glibc Linux arm64/x64; hands-on verification is
|
|
72
|
-
recorded separately.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
and
|
|
79
|
-
the
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
customized client skills silently. If interrupted setup leaves `setup.lock`,
|
|
70
|
+
recorded separately. Campus sessions use permission-restricted local keys.
|
|
71
|
+
CI checks clean installation, updates, removal, MCP discovery and synthetic
|
|
72
|
+
browser workflows on macOS, Windows, Linux and both WSL engines. See the
|
|
73
|
+
[development guide](development.md#checks) for the verification layers.
|
|
74
|
+
|
|
75
|
+
`update` downloads and validates the latest release, replaces the invoked npm
|
|
76
|
+
installation and refreshes previously configured clients. `update --local`
|
|
77
|
+
refreshes the installed version without npm. Retained runtimes keep pinned
|
|
78
|
+
clients working, and newer installed versions are not silently downgraded.
|
|
79
|
+
[Update and removal behavior](setup.md#update-and-remove) covers ownership
|
|
80
|
+
receipts, conflict handling and explicit cleanup. `uninstall` removes managed
|
|
81
|
+
clients and npm; `--client NAME` or `--keep-package` retains the package.
|
|
82
|
+
Customized files and saved data are preserved. If interrupted setup leaves `setup.lock`,
|
|
86
83
|
confirm that no setup process is running before removing that directory locally.
|
|
87
84
|
An invalid or incomplete runtime is never selected for serving. Failed validation
|
|
88
85
|
clears its ready marker so explicit setup can rebuild it; older runtimes remain
|
|
@@ -92,7 +89,7 @@ rerun its setup to restore that runtime, reviewing any client configuration diff
|
|
|
92
89
|
For platforms outside the bootstrap targets, the source installation needs
|
|
93
90
|
Python 3.13+, uv, and Git: run `uv sync --locked`, then
|
|
94
91
|
`uv run tum-mcp setup --client generic` from the checkout. An installed Chromium browser is needed for
|
|
95
|
-
browser onboarding. See [setup](setup.md) for browser choices and WSL.
|
|
92
|
+
browser onboarding. See [setup](setup.md) for browser choices and WSL.
|
|
96
93
|
|
|
97
94
|
## Connections and scopes
|
|
98
95
|
|
|
@@ -101,17 +98,16 @@ tum-mcp connect
|
|
|
101
98
|
tum-mcp status
|
|
102
99
|
tum-mcp discover artemis ACCOUNT_ID
|
|
103
100
|
tum-mcp discover zulip ACCOUNT_ID
|
|
104
|
-
tum-mcp scope artemis ACCOUNT_ID --course COURSE_ID --sensitive
|
|
101
|
+
tum-mcp scope artemis ACCOUNT_ID --course COURSE_ID --sensitive
|
|
105
102
|
tum-mcp scope zulip ACCOUNT_ID --channel CHANNEL_ID
|
|
106
103
|
```
|
|
107
104
|
|
|
108
105
|
`connect` takes no arguments or connection options. Move with up/down, toggle
|
|
109
106
|
services with Space, and press Enter. Choose a browser when more than one is
|
|
110
107
|
installed. Only selected tabs open in one temporary browser context. Moodle,
|
|
111
|
-
Artemis and Zulip all follow this flow
|
|
108
|
+
Artemis and Zulip all follow this flow.
|
|
112
109
|
Sign-in/MFA stays in the browser. `TERM=dumb` uses numbered prompts. Ctrl+C
|
|
113
|
-
cancels and retains completed connections.
|
|
114
|
-
`--service`/`--auth` flags are rejected before any browser opens.
|
|
110
|
+
cancels and retains completed connections.
|
|
115
111
|
|
|
116
112
|
Detection covers Chrome, Edge, Brave, Chromium, Vivaldi, Opera and selected
|
|
117
113
|
preview channels. Set `TUM_MCP_BROWSER` to an executable path for another
|
|
@@ -121,48 +117,30 @@ Only service-owned cookies are saved; identity-provider cookies are discarded
|
|
|
121
117
|
when the temporary browser closes. Existing browser profiles are never imported.
|
|
122
118
|
|
|
123
119
|
Zulip uses its read-only `/json/` routes with the browser session; no API key is
|
|
124
|
-
required. Reconnect through the same selector when a session expires.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
remaining in `--channel ID`. `--sensitive` enables own Artemis participation and
|
|
131
|
-
feedback reads; `--workspace` separately enables preparation under the configured
|
|
132
|
-
workspace root. Neither authorizes submission.
|
|
133
|
-
|
|
134
|
-
On 24 October 2026, both saved browser-session credentials passed identity
|
|
135
|
-
verification through the actual MCP process. Scoped Artemis exercise listing and
|
|
136
|
-
statement retrieval, plus a bounded Zulip channel search, passed. No participation
|
|
137
|
-
was started, code pushed, message sent, or read flag changed by these checks.
|
|
120
|
+
required. Reconnect through the same selector when a session expires.
|
|
121
|
+
See [Zulip's dispatcher](https://github.com/zulip/zulip/blob/12.0/zerver/lib/rest.py).
|
|
122
|
+
Existing scopes survive reconnection; new identities start with empty scopes.
|
|
123
|
+
Private Zulip channels require `--private-channel ID` as well as `--channel ID`.
|
|
124
|
+
`--sensitive` enables own Artemis participation/feedback reads. It grants no
|
|
125
|
+
website mutation or local execution permission.
|
|
138
126
|
|
|
139
127
|
Settings live outside the installed package in `TUMMCP/config/preferences.json`.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
campus connections deliberately do not read or migrate native-store secrets;
|
|
143
|
-
reconnect each service once to use local-file storage. The combined MCP process
|
|
144
|
-
uses that storage for all `moodle_*` compatibility tools. The separate Moodle-only
|
|
145
|
-
installer keeps its native-store default.
|
|
146
|
-
Previously imported Artemis Git tokens also need re-importing into the new store;
|
|
147
|
-
browser sign-in does not import them or open the old native store.
|
|
148
|
-
|
|
149
|
-
New Moodle sessions live under `TUMMoodle/local-session/`; campus credentials live
|
|
150
|
-
under `TUMMCP/credentials/local/`. Each directory has an independent `session.key`.
|
|
128
|
+
Moodle sessions live under `TUMMoodle/local-session/`; Artemis and Zulip credentials
|
|
129
|
+
live under `TUMMCP/credentials/local/`. Each directory has an independent `session.key`.
|
|
151
130
|
Encrypted records and keys have owner-only permissions: 0700 directories / 0600
|
|
152
131
|
keys on POSIX; protected current-user DACLs on Windows through PowerShell. No
|
|
153
|
-
administrator privileges are requested. This avoids
|
|
132
|
+
administrator privileges are requested. This avoids native credential-store
|
|
154
133
|
prompts but protects less than a native store. A copy of both ciphertext and key
|
|
155
134
|
is sufficient to decrypt a session. Do not share, sync publicly, or package them.
|
|
156
135
|
|
|
157
136
|
Missing or damaged keys fail closed. Restore the matching key from a private
|
|
158
137
|
backup. To start fresh, stop clients and move the affected **local storage folder**
|
|
159
|
-
to a private backup before reconnecting
|
|
160
|
-
|
|
161
|
-
Native-store records remain available to the older installation for rollback.
|
|
138
|
+
to a private backup before reconnecting. Keep downloaded course materials when
|
|
139
|
+
repairing a login.
|
|
162
140
|
|
|
163
141
|
Zulip message text is retrieved live and is not persisted. Retrieved excerpts may
|
|
164
|
-
be transmitted to the coding agent's configured AI provider. Moodle
|
|
165
|
-
|
|
142
|
+
be transmitted to the coding agent's configured AI provider. Moodle caches
|
|
143
|
+
documents and extracted text locally in plaintext.
|
|
166
144
|
|
|
167
145
|
Course nicknames can be mapped in `mappings` using explicit per-service IDs.
|
|
168
146
|
The tools resolve one exact mapping; ambiguity never grants broader access.
|
|
@@ -171,75 +149,64 @@ The tools resolve one exact mapping; ambiguity never grants broader access.
|
|
|
171
149
|
|
|
172
150
|
`doctor` reads local configuration and checks runtime prerequisites. It does not
|
|
173
151
|
open a browser, contact campus services, decrypt sessions, or read native stores.
|
|
174
|
-
Saved sessions are **Not verified** until checked.
|
|
175
|
-
|
|
152
|
+
Saved sessions are **Not verified** until checked. Git and Docker are not
|
|
153
|
+
prerequisites. Client registration is distinguished
|
|
176
154
|
from activation; the host must confirm a running MCP connection after setup.
|
|
177
155
|
|
|
178
156
|
Use `doctor --live` for bounded authenticated identity checks on saved local
|
|
179
|
-
sessions
|
|
157
|
+
sessions and optional GitHub CLI authentication. Campus checks read Moodle's
|
|
158
|
+
course overview and Artemis/Zulip identity only;
|
|
180
159
|
it does not broaden content scopes. `doctor --json` emits schema-versioned JSON
|
|
181
160
|
without terminal styling; combine both flags for live automation. Paths appear
|
|
182
161
|
in JSON for troubleshooting. Default diagnostics do not create state folders.
|
|
183
162
|
|
|
184
|
-
##
|
|
163
|
+
## Study workflows
|
|
185
164
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
165
|
+
`read-content` retrieves course information across the three websites. `sync-study`
|
|
166
|
+
uses read-only local status to initialize an explicitly chosen available course or
|
|
167
|
+
reconcile an existing project. Incomplete state is preserved for recovery.
|
|
168
|
+
`prepare-study` creates or extends its local interactive site. See the
|
|
169
|
+
[study guide](study.md) for examples, state structure and helper commands.
|
|
190
170
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
The hidden clone URL must match the server-reported participation repository.
|
|
196
|
-
It is sanitized before storage/output. A narrow Git credential helper supplies
|
|
197
|
-
the token only to that HTTPS repository. Clone uses no inherited credential
|
|
198
|
-
helpers, external Git protocols, hooks, submodules, or dependency installers.
|
|
199
|
-
Existing unrelated/dirty work is preserved. Local receipt files contain IDs,
|
|
200
|
-
workspace, mode, branch, and revision, never tokens.
|
|
201
|
-
|
|
202
|
-
Configure `test_recipes` locally with a unique `name`, exact `account_id`,
|
|
203
|
-
`course_id`, an image pinned as `registry/image@sha256:DIGEST`, an `argv` array,
|
|
204
|
-
`timeout_seconds`, and `verification_level` (`targeted` by default, or `full`
|
|
205
|
-
after reviewing the complete test command). Submission preflight requires a
|
|
206
|
-
passing `full` recipe for the exact content. Review the recipe and obtain its
|
|
207
|
-
image/dependencies as a separate step. The runner uses an already-present image (`--pull=never`), no
|
|
208
|
-
network, no home/keychain/SSH mounts, a read-only container filesystem, dropped
|
|
209
|
-
capabilities, and CPU/memory/process/time/output limits. Only the assignment
|
|
210
|
-
workspace is mounted read/write, with its Git metadata mounted read-only.
|
|
211
|
-
Receipts record exit status, source fingerprints, recipe, image, timestamps,
|
|
212
|
-
and bounded output. A missing engine or recipe fails
|
|
213
|
-
closed. Evidence is encrypted/authenticated outside the assignment directory;
|
|
214
|
-
editing a workspace JSON file cannot fabricate a passing receipt. Ordinary
|
|
215
|
-
host-native testing does not acquire these isolation guarantees.
|
|
171
|
+
One project holds one course. Source revisions, coverage and course knowledge
|
|
172
|
+
avoid unnecessary rereads. Edited files and customized site templates are kept;
|
|
173
|
+
changed sources invalidate dependent units. Study projects, originals and learner
|
|
174
|
+
progress are preserved during package updates/removal.
|
|
216
175
|
|
|
217
176
|
## Client and skill setup
|
|
218
177
|
|
|
219
178
|
`setup --client codex` prepares a local plugin/marketplace entry using the
|
|
220
|
-
portable Agent Plugins schemas. Enable it in
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
The old installation remains available for rollback. Setup reports required UI
|
|
224
|
-
steps and never equates writing files with activation.
|
|
179
|
+
portable Agent Plugins schemas. Enable it in Codex Plugins, restart, and verify
|
|
180
|
+
real tool and skill loading. Setup reports required UI steps and never equates
|
|
181
|
+
writing files with activation.
|
|
225
182
|
|
|
226
183
|
The Codex adapter uses a contained Node launcher to pin the managed Python in
|
|
227
184
|
isolated mode; portable stdio manifests require a bare or contained executable.
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
185
|
+
The shipped pack contains five skills: `read-content`, `sync-study`,
|
|
186
|
+
`prepare-study`, `audio-notes` and `publish-study`. Website-specific retrieval
|
|
187
|
+
guidance is loaded from references within read-content. Teaching, schema and design contracts live
|
|
188
|
+
with prepare-study; the renderer and synthetic example ship as reusable assets.
|
|
189
|
+
Audio Notes converts prepared content into category tracks and maintains coverage,
|
|
190
|
+
scripts, voice settings, candidates and archives under the course's `audio/` root.
|
|
191
|
+
Publish Study uses host GitHub CLI authentication to create a private repository
|
|
192
|
+
and a public Pages website after explicit publication consent. It chooses a course
|
|
193
|
+
and semester name, updates the same site after successful study builds, and shows
|
|
194
|
+
the hosted URL alongside the local launcher URL. No tokens or original course
|
|
195
|
+
downloads are uploaded. See [publishing](study.md#publish-a-study-website).
|
|
196
|
+
Old seven-skill, three-site and separate init/update packs are retired only when
|
|
197
|
+
managed copies remain unchanged. Personal overrides are preserved and require a deliberate merge into
|
|
198
|
+
the consolidated workflows before export.
|
|
199
|
+
|
|
200
|
+
`scripts/verify_campus_clients.py` checks real host discovery in disposable
|
|
201
|
+
profiles without running a model or changing actual user profiles. Host/model
|
|
202
|
+
routing quality is a separate evaluation from structural and discovery checks.
|
|
203
|
+
Claude's invocation metadata follows each workflow's selected policy; automatic
|
|
204
|
+
selection is enabled by default and never grants permission for a mutation.
|
|
205
|
+
|
|
206
|
+
`setup --client cursor` writes `~/.cursor/mcp.json` and installs all five skills
|
|
207
|
+
under `~/.cursor/skills/`.
|
|
208
|
+
`setup --client antigravity` installs the same skills under `~/.gemini/config/skills/`
|
|
209
|
+
and writes `~/.gemini/config/mcp_config.json`; an existing
|
|
243
210
|
legacy `~/.gemini/antigravity/mcp_config.json` is reused when no current file exists.
|
|
244
211
|
Both merge the `tum` stdio entry and preserve unrelated settings.
|
|
245
212
|
From WSL, append `--host windows` to any client setup command to target its
|
|
@@ -253,18 +220,25 @@ in the host after setup; actual host activation is not certified by writing file
|
|
|
253
220
|
See the official [Cursor MCP documentation](https://cursor.com/docs/mcp) and
|
|
254
221
|
[Antigravity MCP documentation](https://antigravity.google/docs/mcp).
|
|
255
222
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
223
|
+
Both adapters install complete skill bundles, including references and website
|
|
224
|
+
assets. Existing MCP-only registrations gain skills through setup or `tum-mcp update`.
|
|
225
|
+
Ownership receipts track installed files: updates replace only unchanged managed
|
|
226
|
+
files, and uninstall removes only unchanged managed files and the MCP entry.
|
|
227
|
+
An edited managed file blocks that client's update or uninstall for review.
|
|
228
|
+
Unrelated skills, extra user files, sessions and personal work stay intact.
|
|
229
|
+
Without an ownership receipt, uninstall preserves manually installed skills.
|
|
230
|
+
Restart the client and verify that its skills and MCP tools appear; writing files
|
|
231
|
+
does not establish model-routing quality or native desktop activation.
|
|
232
|
+
See the official [Cursor skills guide](https://cursor.com/help/customization/skills)
|
|
233
|
+
and [Antigravity skills guide](https://antigravity.google/docs/skills?app=antigravity-ide).
|
|
234
|
+
|
|
235
|
+
Manual export remains available for other clients or a separate reviewed copy:
|
|
262
236
|
|
|
263
237
|
```sh
|
|
264
238
|
tum-mcp skills list
|
|
265
|
-
tum-mcp skills inspect
|
|
266
|
-
tum-mcp skills customize
|
|
267
|
-
tum-mcp skills diff
|
|
239
|
+
tum-mcp skills inspect read-content
|
|
240
|
+
tum-mcp skills customize read-content
|
|
241
|
+
tum-mcp skills diff read-content
|
|
268
242
|
tum-mcp skills validate
|
|
269
243
|
tum-mcp skills export /path/to/new/export-folder
|
|
270
244
|
```
|
|
@@ -278,28 +252,27 @@ trials, and two review passes have not been demonstrated for this pilot.
|
|
|
278
252
|
Export refuses symbolic links and
|
|
279
253
|
does not overwrite an existing destination.
|
|
280
254
|
|
|
281
|
-
The
|
|
282
|
-
|
|
283
|
-
missing credentials
|
|
255
|
+
The activation corpus covers the reading, study and audio workflows, with
|
|
256
|
+
development and held-out partitions. It covers explicit/implicit requests, unrelated
|
|
257
|
+
negatives, missing credentials and unsupported-action negatives. Old trial
|
|
258
|
+
results must not be reused against the consolidated skill labels. `skills evaluate TRIALS.jsonl` scores supplied fresh-session
|
|
284
259
|
records separately by host/version/model. Each record follows `Trial` in
|
|
285
260
|
`skill_validation.py` and references its retained raw trace by SHA-256. The scorer
|
|
286
261
|
does not launch other agents or certify the supplied traces, summary quality,
|
|
287
262
|
or platform acceptance. Inspect traces and backend effects before approving a
|
|
288
263
|
release; no measured activation accuracy is claimed by the structural checks.
|
|
289
264
|
|
|
290
|
-
##
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
checks
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
Maintainer checks include
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
`tum-mcp status` reports registry state as `not_checked`, since it inspects local
|
|
305
|
-
configuration without making registry requests.
|
|
265
|
+
## Verification and release scope
|
|
266
|
+
|
|
267
|
+
Local source validation, real MCP protocol discovery, installation/migration
|
|
268
|
+
checks and browser study-site QA are separate gates. Model-routing accuracy and
|
|
269
|
+
human SSO/MFA on every desktop are not established by schema tests or generated
|
|
270
|
+
configuration. No measured skill-selection accuracy is claimed.
|
|
271
|
+
|
|
272
|
+
The existing desktop/WSL CI matrix must pass on the exact pushed revision before
|
|
273
|
+
it is described as verified. Test data and public fixtures are synthetic. Real
|
|
274
|
+
course material, local agent notes and screenshots stay under ignored local paths.
|
|
275
|
+
Maintainer checks include a reviewed tarball inventory, integrity checks and an
|
|
276
|
+
isolated consumer install. Never publish or stage npm packages as a test. Registry
|
|
277
|
+
publication is an explicit maintainer action.
|
|
278
|
+
`tum-mcp status` reports registry state as `not_checked`; it reads local configuration.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"wheel": "
|
|
3
|
-
"wheelSha256": "
|
|
4
|
-
"requirementsSha256": "
|
|
2
|
+
"wheel": "tum_mcp-0.6.1-py3-none-any.whl",
|
|
3
|
+
"wheelSha256": "59ecf435716e6c0ab68ed9720f2c137b3236f64dd5e962db4c3bf82b76c45ba2",
|
|
4
|
+
"requirementsSha256": "25f9efa7a4ffb0b97abcfeb9d4706d04808273ab1b35abcfaa1ef0b66e87591b"
|
|
5
5
|
}
|
|
@@ -48,7 +48,7 @@ backports-zstd==1.8.0 ; python_full_version < '3.14' \
|
|
|
48
48
|
beautifulsoup4==4.15.0 \
|
|
49
49
|
--hash=sha256:288e3ca7d54b06f2ac191970bc275c1939cb46d450b255bf6718b04aa37ab4f7 \
|
|
50
50
|
--hash=sha256:d6f88de62e1d4e38ecb1077eb9724cd0eff29d2a08ca16a401e9b9e93f117cf9
|
|
51
|
-
# via tum-
|
|
51
|
+
# via tum-mcp
|
|
52
52
|
brotli==1.2.0 ; platform_python_implementation == 'CPython' \
|
|
53
53
|
--hash=sha256:0cf8c3b8ba93d496b2fae778039e2f5ecc7cff99df84df337ca31d8f2252896c \
|
|
54
54
|
--hash=sha256:1b1d6a4efedd53671c793be6dd760fcf2107da3a52331ad9ea429edf0902f27a \
|
|
@@ -207,15 +207,15 @@ cryptography==47.0.0 \
|
|
|
207
207
|
# via
|
|
208
208
|
# pyjwt
|
|
209
209
|
# secretstorage
|
|
210
|
-
# tum-
|
|
210
|
+
# tum-mcp
|
|
211
211
|
defusedxml==0.7.1 \
|
|
212
212
|
--hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \
|
|
213
213
|
--hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61
|
|
214
|
-
# via tum-
|
|
214
|
+
# via tum-mcp
|
|
215
215
|
filelock==3.32.7 \
|
|
216
216
|
--hash=sha256:37b8a3d9811b0f9aef7e5ec5c71bb320de52df51e6ca9bcd6f5ad81187660da7 \
|
|
217
217
|
--hash=sha256:65ff0d0190ea42038b32bda4b77834fb05be2cad4c5b9b01aa4dfb3614536e52
|
|
218
|
-
# via tum-
|
|
218
|
+
# via tum-mcp
|
|
219
219
|
greenlet==3.5.6 \
|
|
220
220
|
--hash=sha256:06c0e933290fba8ffe53ead4ae1b8044b0e9754b75cebf381aa2bc3e50d82fac \
|
|
221
221
|
--hash=sha256:2ab5f42ac6c238eb71770715e6e909ad9a1a92b6c681ccb64cd5a0f07edb953f \
|
|
@@ -291,7 +291,7 @@ httpx2==2.15.1 \
|
|
|
291
291
|
--hash=sha256:ff75485308fbe441e75b1218546e4e78d884df41e1a9741c1f79335ed8fcfef7
|
|
292
292
|
# via
|
|
293
293
|
# mcp
|
|
294
|
-
# tum-
|
|
294
|
+
# tum-mcp
|
|
295
295
|
httpx2-jsfetch==1.0 ; sys_platform == 'emscripten' \
|
|
296
296
|
--hash=sha256:70a0e3eabfef7cce5ad9c629f7d01ca05e418f586646f4ddf14782e4c1454c60 \
|
|
297
297
|
--hash=sha256:cb916b707601e69a07721aabc8f3f6659be3a6893bc1ff5c6f9e02241df2da32
|
|
@@ -329,7 +329,7 @@ jsonschema==4.26.0 \
|
|
|
329
329
|
--hash=sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce
|
|
330
330
|
# via
|
|
331
331
|
# mcp
|
|
332
|
-
# tum-
|
|
332
|
+
# tum-mcp
|
|
333
333
|
jsonschema-specifications==2025.9.1 \
|
|
334
334
|
--hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \
|
|
335
335
|
--hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d
|
|
@@ -337,7 +337,11 @@ jsonschema-specifications==2025.9.1 \
|
|
|
337
337
|
keyring==25.7.0 \
|
|
338
338
|
--hash=sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f \
|
|
339
339
|
--hash=sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b
|
|
340
|
-
# via tum-
|
|
340
|
+
# via tum-mcp
|
|
341
|
+
latex2mathml==3.81.1 \
|
|
342
|
+
--hash=sha256:c337668441b71c819b6733905a8058ba9a9d767bae11a0c5fdacb3aff31361bd \
|
|
343
|
+
--hash=sha256:c95add0c0fcdecad2d70567e0643050d5ea1149fb2e98a5d5792fb1c8eea2ed5
|
|
344
|
+
# via tum-mcp
|
|
341
345
|
markdown-it-py==4.2.0 \
|
|
342
346
|
--hash=sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49 \
|
|
343
347
|
--hash=sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a
|
|
@@ -345,7 +349,7 @@ markdown-it-py==4.2.0 \
|
|
|
345
349
|
mcp==2.3.0 \
|
|
346
350
|
--hash=sha256:8b147a50441cf059dc88c684e0aeed3687f0aa0f39c6cde7b90330effd2b34d8 \
|
|
347
351
|
--hash=sha256:dd0c44c089d16453e8ae31a3877a0054d7a2314caaa81f5e0541b9b1734b2377
|
|
348
|
-
# via tum-
|
|
352
|
+
# via tum-mcp
|
|
349
353
|
mcp-types==2.3.0 \
|
|
350
354
|
--hash=sha256:968efdbdaedfab06adae40d378a34395f1090c5921d4be3c9cde283aaf76d91d \
|
|
351
355
|
--hash=sha256:d1e46549edb35ee19a94940fcee6d1addd7e589ab7ea92dda83f5d84781fc362
|
|
@@ -420,7 +424,7 @@ pillow==12.3.0 \
|
|
|
420
424
|
--hash=sha256:fa4ecea169a355be7a3ade2c783e2ed12f0e40d2c5621cda8b3297faf7fbb9f5 \
|
|
421
425
|
--hash=sha256:fdafc9cce40277e0f7a0feabce0ee50dd2fa1800f3b38015e51296b5e814048d \
|
|
422
426
|
--hash=sha256:fe3cca2e4e8a592be0f269a1ca4835c25199d9f3ce815c8491048f785b0a0198
|
|
423
|
-
# via tum-
|
|
427
|
+
# via tum-mcp
|
|
424
428
|
playwright==1.64.0 \
|
|
425
429
|
--hash=sha256:2c14d105548876b15bea5e7eca77bf0d8ff4ba0c607c1ae931067f3d1b010369 \
|
|
426
430
|
--hash=sha256:5a59af1b230b234008524a5d42b613b233d4256f73bc1dd25bf3f11db0c81b75 \
|
|
@@ -430,7 +434,7 @@ playwright==1.64.0 \
|
|
|
430
434
|
--hash=sha256:8de42430e9a7c8b04ec963856d484d36ffd452882318ebad2df3e6fb49a8197a \
|
|
431
435
|
--hash=sha256:97a5c247f1130f3343f097caf3bb1e79358d6b6cfa3550d97ecd721d1905911a \
|
|
432
436
|
--hash=sha256:d76a501c9930b5a097b00e2448cda2200122a1e8e4be762ff535c1b076277737
|
|
433
|
-
# via tum-
|
|
437
|
+
# via tum-mcp
|
|
434
438
|
prompt-toolkit==3.0.53 \
|
|
435
439
|
--hash=sha256:01c0891d7f9237d5e339f7d3e42cdae80b7534abb1c7c0e3352efba6231492f2 \
|
|
436
440
|
--hash=sha256:9ec8a0ad96d5c56148b3f914aa79c1564c3fde5d2e6b876e7bc327e353cf8fa6
|
|
@@ -457,7 +461,7 @@ psutil==7.2.2 \
|
|
|
457
461
|
--hash=sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486 \
|
|
458
462
|
--hash=sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00 \
|
|
459
463
|
--hash=sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8
|
|
460
|
-
# via tum-
|
|
464
|
+
# via tum-mcp
|
|
461
465
|
pycparser==3.11 ; implementation_name != 'PyPy' \
|
|
462
466
|
--hash=sha256:51d5a8ba2be0bbe440b99d2112604c95bbbc3c2748a64260186c541e1729cd80 \
|
|
463
467
|
--hash=sha256:d875f09c3507d00e1aba0eecc6dcadc1352f30fff09dc6bff2f1c2935e97c2bc
|
|
@@ -468,7 +472,7 @@ pydantic==2.14.1 \
|
|
|
468
472
|
# via
|
|
469
473
|
# mcp
|
|
470
474
|
# mcp-types
|
|
471
|
-
# tum-
|
|
475
|
+
# tum-mcp
|
|
472
476
|
pydantic-core==2.50.1 \
|
|
473
477
|
--hash=sha256:0036473f5583e6a60e50b8b21651511564277a3f05cc5dab8cf579f552cd5f6c \
|
|
474
478
|
--hash=sha256:009634b83993777ddcd69cad0ffcace43dabde692109528e35f0fde91e386a8b \
|
|
@@ -563,7 +567,7 @@ pyjwt==2.15.1 \
|
|
|
563
567
|
pypdf==6.21.1 \
|
|
564
568
|
--hash=sha256:2d62c383acd6e0dff0a96322ba8b1135229343b084d73c6f6cfd947fd291afcb \
|
|
565
569
|
--hash=sha256:553e2d42f5bb3bb2a785a7d3de8ef90bb7df74b5413eff5a7b4388007ea9254b
|
|
566
|
-
# via tum-
|
|
570
|
+
# via tum-mcp
|
|
567
571
|
pypdfium2==5.14.0 \
|
|
568
572
|
--hash=sha256:09b99c8f0cb427eb17fec13c0862ed598bba34b4843df153f70fff806a2820bc \
|
|
569
573
|
--hash=sha256:11f281613fa22313d9c7ab89947665e84eccf8ebe40e1198a84a88352305648d \
|
|
@@ -588,7 +592,7 @@ pypdfium2==5.14.0 \
|
|
|
588
592
|
--hash=sha256:eb8aeca157808f323e39ea298cc6d6c8e080c192ea2efb1ca81daa0f0ff4d095 \
|
|
589
593
|
--hash=sha256:f1b696e6901e16f114a2ec6332e5e3f8f5033a901614ead28499ab18ca6024f5 \
|
|
590
594
|
--hash=sha256:f6f13bbcc5f4adabc2676e52f662c6cb375de86b314790b0ae08f3ab62eb116a
|
|
591
|
-
# via tum-
|
|
595
|
+
# via tum-mcp
|
|
592
596
|
python-multipart==0.0.32 \
|
|
593
597
|
--hash=sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e \
|
|
594
598
|
--hash=sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23
|
|
@@ -638,11 +642,11 @@ pyyaml==6.0.3 \
|
|
|
638
642
|
--hash=sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be \
|
|
639
643
|
--hash=sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c \
|
|
640
644
|
--hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6
|
|
641
|
-
# via tum-
|
|
645
|
+
# via tum-mcp
|
|
642
646
|
questionary==2.1.1 \
|
|
643
647
|
--hash=sha256:3d7e980292bb0107abaa79c68dd3eee3c561b83a0f89ae482860b181c8bd412d \
|
|
644
648
|
--hash=sha256:a51af13f345f1cdea62347589fbb6df3b290306ab8930713bfae4d475a7d4a59
|
|
645
|
-
# via tum-
|
|
649
|
+
# via tum-mcp
|
|
646
650
|
referencing==0.37.0 \
|
|
647
651
|
--hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \
|
|
648
652
|
--hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8
|
|
@@ -653,7 +657,7 @@ rich==15.0.0 \
|
|
|
653
657
|
--hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb \
|
|
654
658
|
--hash=sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36
|
|
655
659
|
# via
|
|
656
|
-
# tum-
|
|
660
|
+
# tum-mcp
|
|
657
661
|
# typer
|
|
658
662
|
rpds-py==2026.9.1 \
|
|
659
663
|
--hash=sha256:00ba2d8c7dd4ee537978ddf4b3fbd712bef2d8751603f7f3146b3f4287768e25 \
|
|
@@ -764,7 +768,7 @@ truststore==0.10.5 ; sys_platform != 'emscripten' \
|
|
|
764
768
|
typer==0.27.3 \
|
|
765
769
|
--hash=sha256:d0396f770a560ab1b0a8504e13b5f254b728cedb05c61cf0359e944e50ce8901 \
|
|
766
770
|
--hash=sha256:e50022f28b82a86313e54501317a1db64bf8f8d036ff8cfe5ca7e47675454aff
|
|
767
|
-
# via tum-
|
|
771
|
+
# via tum-mcp
|
|
768
772
|
typing-extensions==4.16.0 \
|
|
769
773
|
--hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \
|
|
770
774
|
--hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5
|
|
Binary file
|
package/npm/lock.mjs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { mkdir, rename, rm, rmdir, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { hostname } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
|
|
7
|
+
export async function acquireLock(root, name = 'setup') {
|
|
8
|
+
await mkdir(root, { recursive: true, mode: 0o700 });
|
|
9
|
+
const lock = join(root, `${name}.lock`);
|
|
10
|
+
const owner = { pid: process.pid, host: hostname(), nonce: randomUUID() };
|
|
11
|
+
const guard = join(root, `${name}.claim`);
|
|
12
|
+
try { await mkdir(guard, { mode: 0o700 }); }
|
|
13
|
+
catch { throw new Error(`Another ${name} is claiming the lock. Retry; an interrupted ${name}.claim needs local review.`); }
|
|
14
|
+
try {
|
|
15
|
+
try { await mkdir(lock, { mode: 0o700 }); }
|
|
16
|
+
catch (error) {
|
|
17
|
+
if (error.code !== 'EEXIST') throw error;
|
|
18
|
+
let previous;
|
|
19
|
+
try { previous = JSON.parse(readFileSync(join(lock, 'owner.json'), 'utf8')); }
|
|
20
|
+
catch { throw new Error(`${name} lock has no readable owner. Confirm no operation is running before removing ${name}.lock.`); }
|
|
21
|
+
if (!Number.isSafeInteger(previous.pid) || previous.pid <= 0 || previous.host !== hostname()) {
|
|
22
|
+
throw new Error(`${name} lock belongs to an unknown owner; preserve it for local review.`);
|
|
23
|
+
}
|
|
24
|
+
let alive = true;
|
|
25
|
+
try { process.kill(previous.pid, 0); }
|
|
26
|
+
catch (failure) { if (failure.code === 'ESRCH') alive = false; }
|
|
27
|
+
if (alive) throw new Error(`Another ${name} is running; retry when it finishes.`);
|
|
28
|
+
const abandoned = `${lock}.${randomUUID()}.abandoned`;
|
|
29
|
+
await rename(lock, abandoned);
|
|
30
|
+
await rm(abandoned, { recursive: true, force: true });
|
|
31
|
+
try { await mkdir(lock, { mode: 0o700 }); }
|
|
32
|
+
catch { throw new Error(`Another ${name} acquired the lock; retry when it finishes.`); }
|
|
33
|
+
}
|
|
34
|
+
const temporary = join(lock, `${owner.nonce}.pending`);
|
|
35
|
+
await writeFile(temporary, JSON.stringify(owner), { mode: 0o600, flag: 'wx' });
|
|
36
|
+
await rename(temporary, join(lock, 'owner.json'));
|
|
37
|
+
} finally { await rmdir(guard); }
|
|
38
|
+
return async () => {
|
|
39
|
+
const current = JSON.parse(readFileSync(join(lock, 'owner.json'), 'utf8'));
|
|
40
|
+
if (current.nonce !== owner.nonce) throw new Error(`${name} lock ownership changed; it was preserved.`);
|
|
41
|
+
await rm(lock, { recursive: true, force: true });
|
|
42
|
+
};
|
|
43
|
+
}
|