@jamestesting888/tum-mcp 0.9.0 → 0.9.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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changes
2
2
 
3
+ ## 0.9.1 — 2026-10-27
4
+
5
+ - Make Audio Notes an optional `audio-notes` extension. Keep five base skills,
6
+ preserve existing audio files, and describe all extensions in a compact README table.
7
+
8
+ - Use one compact terminal layout for help, connection status, extensions,
9
+ skills and permissions. Keep automation output available through `--json`.
10
+ - Give setup, install and uninstall matching status-aware pickers. Uninstall
11
+ offers full package removal through All. Keep named commands for scripts and
12
+ show optional workflow state through status, connect and doctor; remove the
13
+ separate extensions command group. Studocu browser sign-in stays unverified.
14
+ - Include TUMonline connection and permission status in doctor. Default checks
15
+ do not read credentials or create policy files; live checks verify identity
16
+ without fetching studies or grades.
17
+ - Make unverified status dots blue, ready/enabled green, action needed amber,
18
+ failures red and inactive states muted. Preserve labels with color disabled.
19
+
3
20
  ## 0.9.0 — 2026-10-26
4
21
 
5
22
  - Add read-only TUMonline study, public catalog and partial curriculum-position
package/README.md CHANGED
@@ -13,12 +13,12 @@ Requires **Node.js 22.14+**, a Chromium browser and your TUM account.
13
13
 
14
14
  ```sh
15
15
  npm install --global @jamestesting888/tum-mcp@latest
16
- tum-mcp setup --client codex
16
+ tum-mcp setup
17
17
  tum-mcp connect
18
18
  tum-mcp doctor
19
19
  ```
20
20
 
21
- Choose `codex`, `claude`, `cursor`, `antigravity` or `generic` as the client.
21
+ Select `codex`, `claude`, `cursor`, `antigravity` or `generic`, or pass `--client NAME`.
22
22
  Follow the activation/restart instructions. In `connect`, select services with
23
23
  **Space**, then **Enter**, and complete sign-in/MFA in the browser. Never paste
24
24
  credentials into chat. Setup supplies its own Python runtime; Git, Docker and a
@@ -40,7 +40,6 @@ submissions, posting and exercise execution are unavailable.
40
40
  | `sync-course` | “Set up a project for this course and collect its materials.” |
41
41
  | `prepare-study` | “Build lessons, flashcards and practice in a study website.” |
42
42
  | `prepare-exercises` | “Add guided exercises from this week's released sheet.” |
43
- | `audio-notes` | “Turn the prepared lessons into audio notes.” |
44
43
  | `publish-course` | “Publish my reviewed study site for phone access.” |
45
44
 
46
45
  Each project holds one course. Run `tum-mcp study` in its folder to open the app.
@@ -55,28 +54,21 @@ account policy with `tum-mcp manage tumonline`.
55
54
 
56
55
  ## Optional extensions
57
56
 
58
- Install only the workflows you need, then reload your client:
57
+ Run `tum-mcp install` to choose extensions, then reload your client.
59
58
 
60
- ```sh
61
- tum-mcp install lecture # Prepare Lecture + TUM-Live tools and local ASR
62
- tum-mcp install lecture --no-asr # Use captions/imported WebVTT instead
63
- tum-mcp install studocu # Supplementary Studocu collection workflow
64
- tum-mcp extensions status
65
- ```
66
-
67
- **Lecture Notes** captures the professor's extra explanations, examples and
68
- caveats, with timestamp links. It starts with transcripts and lecture materials;
69
- only critical visuals need recording frames. Local recognition uses Apple Silicon
70
- acceleration or a separate CPU runtime on supported hosts.
71
- [Lecture Notes and recognizer requirements](docs/lecture-notes.md).
59
+ | Extension | Skill added | What it offers |
60
+ | --- | --- | --- |
61
+ | `lecture` | `prepare-lecture` | Lecture Notes with the professor's extra explanations, timestamps and selected critical visuals. Prefers transcripts and slides; local recognition is optional. |
62
+ | `studocu` | `sync-studocu` | Search and collect selected supplementary PDFs saved in your browser. Personal use only; excluded from published sites. |
63
+ | `audio-notes` | `audio-notes` | Turn prepared Study lessons into concise audio tracks, with resumable generation and coverage tracking. Voice setup happens when used. |
72
64
 
73
- **Studocu** adds public search and reviewed import of permitted original PDFs you
74
- save in your browser. Search coverage is incomplete; browser credentials stay out
75
- of the integration. These supplementary materials remain for personal use and
76
- cannot be included in published sites. [Studocu workflow](docs/study.md#studocu-materials).
65
+ Use `tum-mcp status` to see installed workflows and `tum-mcp uninstall` to remove
66
+ them. Named commands also work, such as `tum-mcp install audio-notes` and
67
+ `tum-mcp uninstall lecture`. Existing notes, audio and customizations are retained.
68
+ Audio Notes needs no additional campus sign-in. Studocu uses your own browser.
77
69
 
78
- Remove either extension with `tum-mcp uninstall lecture` or
79
- `tum-mcp uninstall studocu`. Notes, evidence and customizations are preserved.
70
+ [Lecture and recognition](docs/lecture-notes.md) ·
71
+ [Studocu collection](docs/study.md#studocu-materials) · [Setup details](docs/setup.md)
80
72
 
81
73
  ## Privacy, updates and removal
82
74
 
@@ -40,7 +40,7 @@ Each layer owns a different failure boundary:
40
40
  | Unit | Parsing, policy, malformed input and failure branches with synthetic collaborators |
41
41
  | Integration | Real files, CLI/MCP, transactions, HTTP confinement and isolated project updates |
42
42
  | Installed consumer | Actual npm/wheel contents, managed runtime and complete browser workflows |
43
- | Public upgrade | Earlier published versions, repair, ownership conflicts and removal |
43
+ | Public upgrade | Published 0.9.0, repair, ownership conflicts and removal |
44
44
  | Native platform | OS credential/ACL behavior; WSL Windows browser transport on both engines |
45
45
 
46
46
  Study integration fixtures build the private rich regression fixture once, then copy it into a fresh
@@ -59,8 +59,9 @@ CI runs macOS, Windows and Linux, plus both distribution engines on WSL 3.x.
59
59
  Consumer checks install the actual npm artifact, discover tools, build a study
60
60
  site and test available Chromium browsers with temporary profiles and synthetic
61
61
  pages. WSL verifies Windows browser transport. No live account is used.
62
- Upgrade checks cover public 0.8.0 and 0.8.1, client refresh, customized-file conflicts,
63
- failed preparation, runtime repair and removal that preserves work/credentials.
62
+ Upgrade checks start from public 0.9.0 and cover all five clients, optional-extension
63
+ retention, customized-file conflicts, failed preparation, runtime repair and
64
+ removal that preserves work/credentials. Earlier releases are outside this matrix.
64
65
  The package-lifecycle check uses a local synthetic registry and real isolated
65
66
  global npm prefixes to verify downloads, backend validation, replacement,
66
67
  failure ordering and one-command removal. It does not publish a test release.
@@ -143,7 +144,7 @@ check keyboard navigation, reduced motion, source links and retained progress.
143
144
 
144
145
  ## Optional Lecture extension
145
146
 
146
- Base setup exposes six workflows and no `tum_live_*` tools. `install lecture`
147
+ Base setup exposes five workflows and no `tum_live_*` tools. `install lecture`
147
148
  records explicit selection, refreshes managed clients and provisions the optional
148
149
  recognizer only when requested/supported. `--no-asr` keeps captions/imported WebVTT.
149
150
  Heavy recognition dependencies and model weights stay outside the base environment
@@ -152,7 +153,7 @@ and package artifacts. `lecture_processing/` owns bounded media/ASR evidence;
152
153
  and figures used by the static app. See [the workflow guide](lecture-notes.md).
153
154
 
154
155
  Use `skills validate --all` to check the packaged optional workflow without installing
155
- it; default validation checks the selected six/seven. Activation statistics remain
156
+ it; default validation checks the selected workflows. Activation statistics remain
156
157
  unmeasured until genuine fresh-session trial records exist. Default tests use
157
158
  synthetic media and course data. `test:consumer` and `test:upgrade` exercise optional
158
159
  install/update/export/removal from an actual local npm artifact. Never publish or
@@ -9,7 +9,7 @@ tum-mcp install lecture --no-asr
9
9
  ```
10
10
 
11
11
  Restart the coding client to load Prepare Lecture and the three TUM-Live metadata
12
- tools. Base setup keeps its six skills and existing services. Removing the option
12
+ tools. Base setup keeps its five skills and existing services. Removing the option
13
13
  with `tum-mcp uninstall lecture` preserves course notes, evidence, sessions,
14
14
  model caches and customizations. Reinstalling can reuse them.
15
15
 
package/docs/setup.md CHANGED
@@ -19,30 +19,59 @@ tum-mcp doctor
19
19
  tum-mcp --help
20
20
  ```
21
21
 
22
- Use `--client claude`, `cursor`, `antigravity`, or `generic` for another client.
22
+ Run `tum-mcp setup` to choose clients interactively, or pass `--client claude`,
23
+ `cursor`, `antigravity`, or `generic` directly. Existing registrations have status dots.
23
24
  Codex needs the plugin enabled and a restart when prompted. Cursor and
24
- Antigravity setup installs all six base skills and MCP configuration; restart each
25
+ Antigravity setup installs all five base skills and MCP configuration; restart each
25
26
  client afterward. Existing MCP-only setups gain the skills through `tum-mcp update`
26
27
  or another setup run. Generic setup writes configuration for manual installation.
27
28
 
28
29
  Studocu is optional: run `tum-mcp install studocu`, then reload the client. The
29
- extension adds the `sync-studocu` skill and its tools. `tum-mcp extensions status`
30
- reports the local selection; `tum-mcp extensions remove studocu` disables it and
30
+ extension adds the `sync-studocu` skill and its tools. `tum-mcp status`
31
+ reports the local selection; `tum-mcp uninstall studocu` disables it and
31
32
  preserves course materials and customized files. Generic clients use
32
33
  `tum-mcp skills export DESTINATION` to install the active pack manually.
33
34
  Setup preserves unrelated settings and refuses to
34
35
  replace customized entries. It does not authenticate or fetch courses.
35
36
 
37
+ Audio Notes is optional: use `tum-mcp install audio-notes`. It adds the
38
+ `audio-notes` skill for prepared Study content; synthesis is set up when used.
39
+ Existing course audio is retained when the extension is disabled.
40
+
41
+ ## Terminal output
42
+
43
+ `tum-mcp status` shows saved connections and optional workflows;
44
+ `tum-mcp doctor` also checks clients and prerequisites, including TUMonline.
45
+ Green dots mean ready or enabled, blue means not verified, amber means action
46
+ needed, red means failed, and muted dots mean inactive. Every dot has a text
47
+ label. `NO_COLOR` disables color; narrow terminals use stacked rows.
48
+
49
+ Bare `tum-mcp setup`, `tum-mcp install` and `tum-mcp uninstall` share the same
50
+ keyboard controls as connect. Nothing is preselected; Ctrl+C cancels. Uninstall
51
+ also offers **All — TUM MCP**, which removes the package and managed client setup.
52
+ Personal notes, sessions and customized files are retained. Scripts can name one or both:
53
+ `tum-mcp uninstall lecture studocu --json`.
54
+
55
+ Use `--json` for machine-readable status, named extension removal/installation,
56
+ skill listing/validation, lecture runtime status or TUMonline permissions.
57
+ The default human output changed in 0.9.1; scripts that parsed those commands
58
+ must add `--json`. The former `extensions` group is removed; use `status` and
59
+ `uninstall NAME`. Named client/extension arguments remain suitable for scripts.
60
+ Data-oriented course authoring commands retain JSON output.
61
+
36
62
  ## Connect
37
63
 
38
64
  Run **`tum-mcp connect`**, with no arguments, in an interactive terminal:
39
65
 
40
- 1. Use up/down to move and Space to select Moodle, Artemis, Zulip and/or TUMonline.
66
+ 1. Use up/down to move and Space to select services. Installed Lecture adds TUM-Live;
67
+ installed Studocu adds Studocu.
41
68
  2. Press Enter. If several browsers are installed, choose one and press Enter.
42
69
  3. Complete TUM sign-in/MFA in the opened window. Only selected service tabs open.
43
70
  4. Return to the terminal for the saved-connection result.
44
71
 
45
- The services use the same temporary-browser sign-in and encrypted session storage flow.
72
+ Campus services use temporary-browser sign-in and encrypted session storage.
73
+ Studocu opens your own default browser (the Windows browser from WSL); sign in
74
+ there. Its browser session is neither copied nor claimed as verified.
46
75
  No API key or native credential-store prompt is needed. A temporary browser
47
76
  profile keeps the connection separate from your everyday browser. Ctrl+C closes it and preserves
48
77
  connections that already completed. A dumb terminal uses numbered prompts.
@@ -167,6 +196,7 @@ the npm package and all managed registrations:
167
196
 
168
197
  ```sh
169
198
  tum-mcp uninstall
199
+ # Choose All to remove TUM MCP and its managed client setup.
170
200
  ```
171
201
 
172
202
  Custom edits and user-added files are preserved. Codex's local source/catalog
package/docs/study.md CHANGED
@@ -1,9 +1,14 @@
1
1
  # Course study projects
2
2
 
3
- Six base skills cover source reading, course sync, Study preparation, Exercises preparation, audio and publishing.
3
+ Five base skills cover source reading, course sync, Study preparation, Exercises
4
+ preparation and publishing. They run in your local agent, using the connected
5
+ MCP tools to read course sources. The CLI validates and stores the resulting local
6
+ files; it does not run an AI model.
4
7
  The optional `prepare-lecture` skill adds a Lecture Notes workspace; install it with
5
8
  `tum-mcp install lecture`. See [Lecture Notes](lecture-notes.md).
6
9
  The optional `sync-studocu` skill collects selected student-uploaded material separately.
10
+ The optional `audio-notes` skill turns prepared lessons into spoken tracks; install
11
+ it with `tum-mcp install audio-notes`.
7
12
 
8
13
  ## Studocu materials
9
14
 
@@ -32,13 +37,10 @@ consolidated. Edited or missing files are preserved for review.
32
37
  Local study material can cite student uploads. Publishing rejects included
33
38
  Studocu-backed sources; this source check cannot identify uncited copied text or
34
39
  replace a review of the published content.
35
- They run in your local agent, using the connected
36
- MCP tools to read course sources. The CLI validates and stores the resulting local
37
- files; it does not run an AI model.
38
40
 
39
41
  ## Publish a study website
40
42
 
41
- The optional `publish-course` skill makes a prepared site accessible from a phone
43
+ The `publish-course` skill makes a prepared site accessible from a phone
42
44
  or another computer. Its GitHub repository is private; the Pages website is
43
45
  public. An eligible paid GitHub plan is required for Pages from private repositories.
44
46
  This workflow does not provide private website access. Review lesson text,
@@ -312,6 +314,7 @@ is a no-op. Do not create `app/` alongside an existing `study/` by hand.
312
314
 
313
315
  ## Create and maintain audio notes
314
316
 
317
+ Install the optional workflow with `tum-mcp install audio-notes`.
315
318
  Use `prepare-study` to author the interactive course, then ask `audio-notes` to
316
319
  convert that prepared content into spoken lessons. For example:
317
320
 
package/docs/tum-mcp.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Package: `@jamestesting888/tum-mcp`, CLI: `tum-mcp`, backend: Python 3.13.
4
4
  The package combines read-only course retrieval, managed client installation and
5
- six local course workflows.
5
+ five base course workflows and three optional extensions.
6
6
 
7
7
  ## Current capabilities
8
8
 
@@ -225,9 +225,11 @@ writing files with activation.
225
225
 
226
226
  The Codex adapter uses a contained Node launcher to pin the managed Python in
227
227
  isolated mode; portable stdio manifests require a bare or contained executable.
228
- The shipped pack contains six skills: `read-content`, `sync-course`,
229
- `prepare-study`, `prepare-exercises`, `audio-notes` and `publish-course`. Website-specific retrieval
230
- guidance is loaded from references within read-content. Teaching, schema and design contracts live
228
+ The base pack contains five skills: `read-content`, `sync-course`,
229
+ `prepare-study`, `prepare-exercises` and `publish-course`. Optional extensions add
230
+ `prepare-lecture`, `sync-studocu` and `audio-notes`; choose them with `tum-mcp install`.
231
+ Website-specific retrieval guidance is loaded from references within read-content.
232
+ Teaching, schema and design contracts live
231
233
  with prepare-study; the renderer and synthetic example ship as reusable assets.
232
234
  Audio Notes converts prepared content into category tracks and maintains coverage,
233
235
  scripts, voice settings, candidates and archives under the course's `audio/` root.
@@ -246,7 +248,7 @@ routing quality is a separate evaluation from structural and discovery checks.
246
248
  Claude's invocation metadata follows each workflow's selected policy; automatic
247
249
  selection is enabled by default and never grants permission for a mutation.
248
250
 
249
- `setup --client cursor` writes `~/.cursor/mcp.json` and installs all six skills
251
+ `setup --client cursor` writes `~/.cursor/mcp.json` and installs the active skills
250
252
  under `~/.cursor/skills/`.
251
253
  `setup --client antigravity` installs the same skills under `~/.gemini/config/skills/`
252
254
  and writes `~/.gemini/config/mcp_config.json`; an existing
@@ -1,5 +1,5 @@
1
1
  {
2
- "wheel": "tum_mcp-0.9.0-py3-none-any.whl",
3
- "wheelSha256": "0af36e0b89e055a49ae7a8cfa144ff98fdd4feb9e82b724e6ee629f8f4e51b7b",
2
+ "wheel": "tum_mcp-0.9.1-py3-none-any.whl",
3
+ "wheelSha256": "69d65afa35c27518f03c95e47ddfc23cc77a3d442853804fcb58c2e78b539fe0",
4
4
  "requirementsSha256": "39a401b6e606d3292eb91b8fe9ef60367d4852f203eb409dc52f38b76e513ccf"
5
5
  }
@@ -72,7 +72,7 @@ async function operate(job) {
72
72
  const staging = join(job.temporary, 'prepared');
73
73
  runNpm(job.npm, ['install', '--prefix', staging, '--global=false', archive], true);
74
74
  const prepared = join(staging, 'node_modules', packageName);
75
- runLauncher(prepared, ['setup'], true);
75
+ runLauncher(prepared, ['setup', '--runtime-only'], true);
76
76
  // Only a healthy prepared release may replace the user's npm installation.
77
77
  runNpm(job.npm, ['install', ...scope, job.target.global ? archive : `${packageName}@${latest}`]);
78
78
  if (JSON.parse(readFileSync(join(job.root, 'package.json'), 'utf8')).version !== latest) throw new Error('npm did not install the selected version; client activation was stopped.');
package/npm/tum-mcp.mjs CHANGED
@@ -4,61 +4,88 @@ import { readFileSync } from 'node:fs';
4
4
  import { parseArgs } from 'node:util';
5
5
  import { acquireSetupLock, currentPython, dataRoot, ensureRuntime, removeRuntimeFiles } from './runtime.mjs';
6
6
  import { managePackage } from './package-manager.mjs';
7
+ import { printHelp } from './ui.mjs';
7
8
 
8
9
  let args = process.argv.slice(2);
9
10
  const version = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
10
11
  try {
11
- if (args.length === 0 || (args.length === 1 && ['--help', '-h'].includes(args[0]))) {
12
- console.log(`TUM MCP ${version}
13
- Usage: tum-mcp COMMAND [OPTIONS]
14
-
15
- setup Configure your coding client and managed runtime
16
- install Install an optional extension: lecture or studocu
17
- connect Sign in to selected campus services
18
- status Show saved connections
19
- discover List accessible courses or channels
20
- doctor Check installation and authentication
21
- update Update the package and configured clients
22
- uninstall Remove managed setup and the npm package
23
- logout Remove one saved connection
24
- serve Run the MCP server over stdio
25
- version Show the installed version
26
- skills Manage local workflow skills
27
- extensions Manage optional extensions
28
- studocu Manage selected Studocu materials
29
- study Prepare, preview and publish a course app
30
-
31
- Use --help for options, for example: tum-mcp study build --help
32
- Run setup to provision the managed backend, then connect to sign in.
33
- Reads use your campus account permissions; no local scope selection is needed.`);
12
+ const wantsHelp = args.length === 0 || args.some(arg => ['--help', '-h'].includes(arg));
13
+ const helpPython = wantsHelp ? currentPython() : null;
14
+ if (helpPython) {
15
+ const forwarded = args.length ? args.filter(arg => !['--local', '--keep-package'].includes(arg)) : ['--help'];
16
+ const env = { ...process.env }; delete env.PYTHONPATH; delete env.PYTHONHOME;
17
+ const child = spawnSync(helpPython, ['-I', '-m', 'tum_mcp', ...forwarded], { env, stdio: 'inherit', shell: false });
18
+ if (child.error) throw new Error('Managed backend could not start; run setup again.');
19
+ process.exitCode = child.status ?? 1;
20
+ } else if (args.length === 0 || (args.length === 1 && ['--help', '-h'].includes(args[0]))) {
21
+ printHelp(version, 'Campus tools and local study workflows.', 'tum-mcp [OPTIONS] COMMAND [ARGS]...', [
22
+ ['Options', [['--version', 'Show the installed version.'], ['-h, --help', 'Show this help.']]],
23
+ ['Commands', [
24
+ ['setup', 'Configure your coding client and managed runtime.'],
25
+ ['connect', 'Sign in to selected campus services.'],
26
+ ['status', 'Show saved connections and optional workflows.'],
27
+ ['doctor', 'Check installation and authentication.'],
28
+ ['install', 'Choose optional Lecture, Studocu or Audio Notes workflows.'],
29
+ ['uninstall', 'Choose extensions or All to remove TUM MCP.'],
30
+ ['manage', 'Manage TUMonline permissions.'],
31
+ ['skills', 'Inspect and validate workflow skills.'],
32
+ ['study', 'Prepare, preview and publish a course app.'],
33
+ ['lecture', 'Prepare lecture recording evidence (optional extension).'],
34
+ ['studocu', 'Collect selected supplementary materials (optional extension).'],
35
+ ['discover', 'List accessible courses or channels.'],
36
+ ['update', 'Update the package and configured clients.'],
37
+ ['logout', 'Remove one saved connection.'],
38
+ ['serve', 'Run the MCP server over stdio.'],
39
+ ['version', 'Show the installed version.'],
40
+ ]],
41
+ ['Get started', [['tum-mcp setup --client codex', 'Prepare the backend and a client.'], ['tum-mcp connect', 'Choose services and sign in.']]],
42
+ ]);
34
43
  } else if (['--version', 'version'].includes(args[0])) {
35
44
  console.log(version);
36
45
  } else if (args[0] === 'install' && args.some(arg => ['--help', '-h'].includes(arg))) {
37
- console.log('Usage: tum-mcp install lecture [--asr|--no-asr] | tum-mcp install studocu\nInstall an optional Lecture or Studocu workflow and its tools. Lecture recognition dependencies are isolated; models load on demand.');
38
- } else if (['setup', 'update', 'uninstall'].includes(args[0]) && !['lecture', 'studocu'].includes(args[1]) && args.some(arg => ['--help', '-h'].includes(arg))) {
46
+ printHelp(version, 'Choose optional workflows to install, or provide their names.', 'tum-mcp install [lecture|studocu|audio-notes]... [OPTIONS]', [
47
+ ['Options', [['--asr / --no-asr', 'Provision isolated lecture recognition; models load on demand.'], ['--json', 'Print machine-readable results.'], ['-h, --help', 'Show this help.']]],
48
+ ]);
49
+ } else if (['setup', 'update', 'uninstall'].includes(args[0]) && args.some(arg => ['--help', '-h'].includes(arg))) {
39
50
  const help = {
40
- update: 'Usage: tum-mcp update [--local]\nInstall the latest npm release and refresh configured clients.\n--local refreshes this installed version without contacting npm.',
41
- setup: 'Usage: tum-mcp setup [--client codex|claude|cursor|antigravity|generic] [--host local|windows]\nProvision the managed runtime and register explicitly selected clients.',
42
- uninstall: 'Usage: tum-mcp uninstall [--all] [--purge-runtime] [--forget-credentials]\nRemove managed client setup and this npm installation. Saved data is retained by default.\n--client NAME removes one client only. --keep-package keeps npm installed.',
51
+ update: {
52
+ description: 'Install the latest npm release and refresh configured clients.',
53
+ usage: 'tum-mcp update [OPTIONS]',
54
+ options: [['--local', 'Refresh the installed version without contacting npm.']],
55
+ },
56
+ setup: {
57
+ description: 'Prepare the runtime and choose coding clients to configure.',
58
+ usage: 'tum-mcp setup [OPTIONS]',
59
+ options: [['--client NAME', 'Choose codex, claude, cursor, antigravity or generic; repeat as needed.'], ['--host local|windows', 'Choose the client host; windows is for WSL registrations.']],
60
+ },
61
+ uninstall: {
62
+ description: 'Remove managed setup while retaining saved user data by default.',
63
+ usage: 'tum-mcp uninstall [lecture|studocu|audio-notes]... [OPTIONS]',
64
+ options: [['(no arguments)', 'Choose extensions or All in the interactive picker.'], ['--client NAME', 'Remove one client registration.'], ['--host local|windows', 'Choose the client host.'], ['--purge-runtime', 'Remove verified runtimes when All is selected.'], ['--forget-credentials', 'Forget saved credentials when All is selected.']],
65
+ },
43
66
  };
44
- console.log(help[args[0]]);
67
+ const selected = help[args[0]];
68
+ printHelp(version, selected.description, selected.usage, [
69
+ ['Options', [...selected.options, ['-h, --help', 'Show this help.']]],
70
+ ]);
45
71
  } else {
46
- if (args[0] === 'install' && !['lecture', 'studocu'].includes(args[1])) throw new Error('Usage: tum-mcp install lecture [--asr|--no-asr] | tum-mcp install studocu.');
72
+ const hasExtension = args.slice(1).some(arg => ['lecture', 'studocu', 'audio-notes'].includes(arg));
47
73
  let packageAction = args[0] === 'update';
48
74
  if (args[0] === 'update') {
49
75
  if (args.length > 2 || (args.length === 2 && args[1] !== '--local')) throw new Error('Usage: tum-mcp update [--local]. Use --help for details.');
50
76
  if (args[1] === '--local') { packageAction = false; args = ['update']; }
51
77
  }
52
- if (args[0] === 'uninstall' && !['lecture', 'studocu'].includes(args[1])) {
78
+ if (args[0] === 'uninstall' && !hasExtension) {
53
79
  const { values } = parseArgs({ args: args.slice(1), options: {
54
80
  all: { type: 'boolean' }, client: { type: 'string' }, host: { type: 'string' },
55
- 'keep-package': { type: 'boolean' }, 'purge-runtime': { type: 'boolean' }, 'forget-credentials': { type: 'boolean' },
81
+ 'keep-package': { type: 'boolean' }, 'purge-runtime': { type: 'boolean' }, 'forget-credentials': { type: 'boolean' }, json: { type: 'boolean' },
56
82
  } });
57
83
  if (values.host && !['local', 'windows'].includes(values.host)) throw new Error('Choose --host local or windows.');
58
84
  if (values.client !== undefined && !['codex', 'claude', 'cursor', 'antigravity', 'generic'].includes(values.client)) throw new Error('Choose a supported --client name.');
59
85
  if (values.client && (values.all || values['purge-runtime'] || values['forget-credentials'])) throw new Error('Client-only removal cannot use --all or data/runtime cleanup options.');
60
- if (!values.client && !values.all) args.push('--all');
61
- packageAction = !values.client && !values['keep-package'];
86
+ if (values.all && values.json) throw new Error('--json requires named extensions.');
87
+ if (values['keep-package'] && !values.all && !values.client) throw new Error('Use --client for registration-only removal.');
88
+ packageAction = Boolean(values.all) && !values['keep-package'];
62
89
  args = args.filter(arg => arg !== '--keep-package');
63
90
  }
64
91
  if (packageAction) {
@@ -69,12 +96,15 @@ Reads use your campus account permissions; no local scope selection is needed.`)
69
96
  if (!python) throw new Error('SETUP_REQUIRED: Run tum-mcp setup first.');
70
97
  const forwarded = args;
71
98
  const env = { ...process.env, TUM_MCP_NPM_LAUNCHER: '1' }; delete env.PYTHONPATH; delete env.PYTHONHOME;
72
- const purge = args[0] === 'uninstall' && args.includes('--purge-runtime');
99
+ const purge = args[0] === 'uninstall' && args.includes('--purge-runtime') && args.includes('--all');
73
100
  const release = purge ? await acquireSetupLock() : null;
74
101
  try {
75
102
  const child = spawnSync(python, ['-I', '-m', 'tum_mcp', ...forwarded], { env, stdio: 'inherit', shell: false });
76
103
  if (child.error) throw new Error('Managed backend could not start; run setup again.');
77
104
  process.exitCode = child.status ?? (child.signal === 'SIGINT' ? 130 : 1);
105
+ if (args[0] === 'uninstall' && child.status === 20) {
106
+ process.exitCode = await managePackage('uninstall', [...args.slice(1), '--all'], dataRoot());
107
+ }
78
108
  if (purge && child.status === 0) await removeRuntimeFiles();
79
109
  } finally { if (release) await release(); }
80
110
  }
package/npm/ui.mjs ADDED
@@ -0,0 +1,51 @@
1
+ // Bootstrap help stays available before Python setup; installed help uses the backend.
2
+ const color = process.stdout.isTTY && !('NO_COLOR' in process.env) && process.env.TERM !== 'dumb';
3
+ const width = Math.min(Number(process.env.COLUMNS) || process.stdout.columns || 80, 100);
4
+ const styled = (text, code) => color ? `\x1b[${code}m${text}\x1b[0m` : text;
5
+
6
+ function line(text, indent = '') {
7
+ const available = Math.max(16, width - indent.length);
8
+ let remaining = text;
9
+ while (remaining.length > available) {
10
+ const space = remaining.lastIndexOf(' ', available);
11
+ const end = space > 0 ? space : available;
12
+ console.log(indent + remaining.slice(0, end));
13
+ remaining = remaining.slice(end).trimStart();
14
+ }
15
+ console.log(indent + remaining);
16
+ }
17
+
18
+ export function printHelp(version, description, usage, sections = []) {
19
+ console.log(`${styled('TUM MCP', '1')} Help ${styled(version, '2')}`);
20
+ line(description);
21
+ console.log();
22
+ line('Usage');
23
+ line(usage, ' ');
24
+ console.log();
25
+ for (const [title, rows] of sections) {
26
+ console.log(styled(title, '1'));
27
+ const labelWidth = Math.max(...rows.map(([label]) => label.length)) + 2;
28
+ for (const [label, detail] of rows) {
29
+ if (width < 70 || labelWidth > width / 2) {
30
+ line(label);
31
+ line(detail, ' ');
32
+ } else {
33
+ const prefix = label.padEnd(labelWidth);
34
+ const available = Math.max(16, width - prefix.length);
35
+ const words = detail.split(' ');
36
+ let row = '';
37
+ let first = true;
38
+ for (const word of words) {
39
+ if (row && row.length + word.length + 1 > available) {
40
+ console.log((first ? prefix : ' '.repeat(labelWidth)) + row);
41
+ first = false;
42
+ row = '';
43
+ }
44
+ row += (row ? ' ' : '') + word;
45
+ }
46
+ console.log((first ? prefix : ' '.repeat(labelWidth)) + row);
47
+ }
48
+ }
49
+ console.log();
50
+ }
51
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jamestesting888/tum-mcp",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Read-only TUM campus tools and source-backed study, exercise and lecture workflows",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "files": [
14
14
  "npm/tum-mcp.mjs",
15
+ "npm/ui.mjs",
15
16
  "npm/runtime.mjs",
16
17
  "npm/download.mjs",
17
18
  "npm/lock.mjs",