Metadata-Version: 2.4
Name: all-abt-ntu-mcp
Version: 0.1.0b4
Summary: MCP server for NTU schedules, learning, career opportunities, maps, research, faculty, library, news, campus services, shuttle arrivals, and student administration
Keywords: ntu,mcp,stars,ntulearn,shuttle,omnibus,careeraxis
Author: pitchaya-s
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Education
Requires-Dist: anyio>=4,<5
Requires-Dist: mcp>=2,<3
Requires-Dist: starlette>=0.48,<2
Requires-Dist: typing-extensions>=4.12,<5
Requires-Dist: pypdf>=6.21.4,<7
Requires-Dist: keyring>=25.6,<27
Requires-Dist: httpx>=0.27,<1
Requires-Dist: tzdata>=2025.1
Requires-Dist: questionary>=2.1,<3
Requires-Dist: browser-cookie3>=0.20,<1 ; extra == 'browser-cookies'
Requires-Dist: playwright>=1.50,<2 ; extra == 'personal'
Requires-Python: >=3.10
Project-URL: Homepage, https://github.com/pitchaya-s/all-abt-ntu-mcp
Project-URL: Repository, https://github.com/pitchaya-s/all-abt-ntu-mcp
Project-URL: Documentation, https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/README.md
Project-URL: Issues, https://github.com/pitchaya-s/all-abt-ntu-mcp/issues
Provides-Extra: browser-cookies
Provides-Extra: personal
Description-Content-Type: text/markdown

# All About NTU MCP

An MCP server for NTU Singapore schedules, learning materials, campus navigation, research, faculty, library discovery, career opportunities, news, campus services, shuttle arrivals, and student administration.

[STARS](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/stars/README.md) · [NTULearn](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/ntulearn/README.md) · [CareerAxis](src/careeraxis/README.md) · [MazeMap](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/mazemap/README.md) · [DR-NTU](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/drntu/README.md) · [Library](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/library/README.md) · [Faculty](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/faculty/README.md) · [News](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/news/README.md) · [Campus services](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/service/README.md) · [NTU Omnibus](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/omnibus/README.md) · [One Stop @ SAC](src/onestop/README.md).

## Quick start

Install [uv](https://docs.astral.sh/uv/) and Python 3.10 or newer, then run setup in your terminal:

```sh
uvx --from 'all-abt-ntu-mcp[personal]@latest' all-abt-ntu setup
```

Choose a profile and select the tool families you want, such as STARS or NTULearn. Setup saves your choices on this machine. Follow the prompts for any additional setup, then connect your client using one of the examples below.

### Choose tools

To list or change families and individual tools later, run:

```sh
uvx --from 'all-abt-ntu-mcp[personal]@latest' all-abt-ntu tools list
uvx --from 'all-abt-ntu-mcp[personal]@latest' all-abt-ntu tools list --all
uvx --from 'all-abt-ntu-mcp[personal]@latest' all-abt-ntu tools disable ntulearn
uvx --from 'all-abt-ntu-mcp[personal]@latest' all-abt-ntu tools enable ntulearn
uvx --from 'all-abt-ntu-mcp[personal]@latest' all-abt-ntu tools disable mazemap_get_directions
uvx --from 'all-abt-ntu-mcp[personal]@latest' all-abt-ntu tools enable mazemap_get_directions
```

Run `setup` again to change your profile or family selection. `tools list` shows families; `--all` shows individual tools. `[~]` means a family is partially enabled. Commands manage tools available in the active profile. Disabling a family also disables tools added to it later. Explicitly enabling a family enables all its tools in the active profile, including actions and downloads; individual tools can then be disabled. Restart the MCP server after changes. Settings do not affect the hosted server.

Without saved settings, the server uses the public profile. See [Configuration file](#configuration-file) for the file format and service settings.

### Profiles

Profiles limit which tools a local server can offer:

- **public:** public information only.
- **personal:** public and authenticated tools, with action and download tools unchecked until you enable them. Newly added action tools also start unchecked.

Setup saves your choice, so you do not need to pass `--profile` normally. The optional flag overrides the saved profile for a particular invocation; disabled tools remain disabled. Actions and downloads require MCP host confirmation; configure your client to show these requests, since a host may answer automatically.

## Custom MCP for Cloud AI

Use this server only if you trust the author of this repository.

In a cloud AI client that supports custom remote MCP servers:

1. Open the MCP or connector settings and add a server with any name you like.
2. Enter this server URL:

   ```text
   https://all-abt-ntu-mcp.vercel.app/mcp
   ```

3. Select **No authentication** and, if asked, **Streamable HTTP** as the transport.
4. Save and enable the server.

The hosted server provides **public tools only**. No NTU credentials are needed. Personal tools, such as NTULearn and saving STARS plans, require the [local setup](#quick-start).

For self-hosting, start with [Manual install](#manual-install). To connect a private server to ChatGPT or other supported OpenAI products, we recommend [OpenAI's `tunnel-client` (Secure MCP Tunnel)](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels). It supports the local stdio server without exposing a public HTTP endpoint.

With other methods, use HTTPS and authentication and review how your data is handled. **Do not expose personal tools through an unauthenticated public endpoint**: they can access private NTU data and act through your saved account.

## Credentials

Public tools need no credentials. When you select personal tools, setup checks for saved credentials and offers to save them if none are found. You can also manage them **yourself in a local terminal**:

```sh
uvx --from 'all-abt-ntu-mcp@latest' all-abt-ntu auth save
```

Your password is hidden while typing and stored encrypted in your OS keyring, rather than in plaintext files. The server never includes it in MCP responses sent to the LLM.

The prompts save one account for STARS, NTULearn, LibFacilities, One Stop and CareerAxis and enable automatic login/session recovery. Run `auth save` again to update it, `auth status` to check storage without revealing credentials, or `auth delete` to remove it. Replace `auth save` at the end of the command above with the action you want.

The keyring must be available and unlocked: Secret Service or KWallet on Linux, Keychain on macOS, Credential Manager on Windows. There is no plaintext fallback. Passwords are not accepted through MCP, command arguments, environment variables, `.env`, or client configuration. Remove any credentials left in your old configuration; the server no longer reads them. More details: [shared credential storage](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/shared/README.md#credential-storage).

Some Linux installations do not include a keyring service. Install a provider such as GNOME Keyring or KWallet using your distribution's package manager, then follow your desktop's setup instructions to start and unlock it before running `auth save`.

## Codex

Add to `~/.codex/config.toml`:

```toml
[mcp_servers.all-abt-ntu-mcp]
command = "uvx"
args = ["--from", "all-abt-ntu-mcp[personal]@latest", "all-abt-ntu"]
env_vars = ["DBUS_SESSION_BUS_ADDRESS", "XDG_RUNTIME_DIR"] # for Linux
startup_timeout_sec = 120
tool_timeout_sec = 240
```

Restart Codex and check `codex mcp list`. Personal tools use your locally saved keyring account. The `env_vars` line forwards the Linux desktop session needed for keyring access; start Codex from a terminal where `auth status` succeeds. These variables contain no NTU credentials.

## Claude Code

Register for your user:

```sh
claude mcp add --scope user all-abt-ntu-mcp \
  -- uvx --from 'all-abt-ntu-mcp[personal]@latest' all-abt-ntu
claude mcp list
```

Personal tools use your locally saved keyring account. Check `claude mcp list` or `/mcp` inside Claude Code. See [Claude Code's MCP guide](https://code.claude.com/docs/en/mcp) for details.

## OpenCode

Add to `~/.config/opencode/opencode.json`:

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "all-abt-ntu-mcp": {
      "type": "local",
      "command": ["uvx", "--from", "all-abt-ntu-mcp[personal]@latest", "all-abt-ntu"],
      "enabled": true,
      "timeout": 240000
    }
  }
}
```

Personal tools use your locally saved keyring account. Check `opencode mcp list`. See [OpenCode's MCP guide](https://docs.opencode.ai/docs/mcp-servers/) for details.

## Manual install

Clone the repository and run the server from a local checkout:

```sh
git clone --branch main https://github.com/pitchaya-s/all-abt-ntu-mcp.git all-abt-ntu-mcp
cd all-abt-ntu-mcp
uv sync
uv run all-abt-ntu
```

For personal tools, run `uv sync --extra personal`, then `uv run all-abt-ntu setup` to choose your tools. See [Credentials](#credentials) to manage your account.

The process uses MCP stdio, so it stays open while its MCP client is connected. Course responses are cached in memory for one hour by default; vacancy snapshots are cached for at most 60 seconds. Set `NTU_CACHE_TTL_SECONDS` to change the cache time or use `0` to disable caching.

### Chromium

The personal profiles require Playwright and its matching Chromium build at startup. If you use the PyPI `uvx` setup, install Chromium from the same package environment as the server:

```sh
uvx --from 'all-abt-ntu-mcp[personal]@latest' playwright install chromium
```

For a repository checkout, run `uv sync --extra personal` followed by `uv run --no-sync playwright install chromium`. Playwright versions can require different Chromium builds, so repeat the matching command after upgrading. NTULearn can optionally reuse an existing browser session without launching Chromium, although the shared personal profiles still require Chromium for their other tools.

### Run an HTTP server on localhost

To connect an MCP client using Streamable HTTP, start the public server from the repository root:

```sh
uv run uvicorn api.index:app --host 127.0.0.1 --port 8000
```

Configure the client with `http://127.0.0.1:8000/mcp` and select **Streamable HTTP**. The server listens only on this computer. This HTTP endpoint provides public tools; personal tools require the local stdio command above.

## Configuration file

Local settings are stored in `$XDG_CONFIG_HOME/all-abt-ntu/tools.json` (normally `~/.config/all-abt-ntu/tools.json`), or `%APPDATA%\all-abt-ntu\tools.json` on Windows. Setup and the CLI update this file. For example:

```json
{
  "profile": "personal",
  "tools": {
    "enabled": ["stars_save_stars_plan"],
    "disabled": ["mazemap_get_directions"],
    "families": {
      "enabled": ["stars", "mazemap"],
      "disabled": ["news"]
    }
  },
  "env": {
    "stars": {"cache_ttl_seconds": 3600},
    "ntulearn": {"headless": false},
    "onestop": {"upload_dir": "/home/me/ntu-uploads"}
  }
}
```

Family settings apply to tools added later. An individually enabled tool can be used within a disabled family; an individually disabled tool stays off within an enabled family. Personal actions and downloads remain disabled unless explicitly enabled. `tools enable` and `tools disable` accept families or individual names and update the file.

All sections are optional; omitted values use their defaults. You can edit the file or use the CLI:

```sh
uv run all-abt-ntu config set ntulearn.headless false
uv run all-abt-ntu config set stars.cache_ttl_seconds 600
uv run all-abt-ntu config list
uv run all-abt-ntu config unset ntulearn.headless
```

For a PyPI install, use the same `uvx --from 'all-abt-ntu-mcp[personal]@latest'` prefix as in Quick start instead of `uv run`. The supported settings under `env` are:

| Group | Settings |
| --- | --- |
| `stars` | `cache_ttl_seconds`, `personal_cache_ttl_seconds` |
| `ntulearn` | `cache_ttl_seconds`, `headless`, `browser_cookies`, `request_concurrency`, `request_interval_seconds`, `timeout_seconds` |
| `careeraxis` | `cache_ttl_seconds`, `headless` |
| `onestop` | `upload_dir` |
| `public_http` | `concurrency`, `interval_seconds`, `timeout_seconds`, `max_retry_delay_seconds` |
| `browser` | `browsers_path` for Playwright |

Use JSON booleans for switches, numbers for durations and limits, and strings for paths. Other environment variables can be stored under `env.other`, for example with `config set other.CUSTOM_SETTING value`. Configuration-location variables such as `XDG_CONFIG_HOME` must be set outside the file. Process environment variables take precedence over saved settings. Restart the server after changing settings. This file is plain text; use the keyring for credentials.

## Source layout

```text
src/
├── cli/                    Local setup, tool selection, and configuration
├── shared/                 Local/public runtimes, HTTP app, keyring, and parsing
├── stars/
│   ├── mcp_server.py        STARS tool registration and input schemas
│   ├── personal_tools.py    Local authenticated STARS tools
│   ├── room_tools.py        Teaching-based room tool registration
│   ├── room_schemas.py      Typed room constraints and results
│   ├── domain/             Course models, timetable matching and room searches
│   ├── client/             Public NTU requests and caching
│   ├── parser/             Schedule and personal-page parsing
│   └── wish/               WISH login and saved-plan editing
├── ntulearn/
│   ├── mcp_server.py        NTULearn tool registration and input schemas
│   ├── models/             Typed responses grouped by domain
│   ├── client/             Login, sessions, and REST requests
│   ├── parser/             Response and document parsing
│   └── services/           Content, files, mailbox, people, and activity
├── careeraxis/
│   ├── mcp_server.py        Local authenticated CareerAxis tools
│   ├── client.py            Section searches and record detail requests
│   ├── session.py           ADFS login and in-memory browser session
│   ├── parser.py            Rendered section and record normalization
│   └── models.py            Search, detail, and auth status responses
├── mazemap/
│   ├── mcp_server.py        Public map tool registration and input schemas
│   ├── models.py           Typed place and direction responses
│   ├── client.py           HTTP requests, pacing, and caching
│   └── parser.py           Place and route normalization
├── drntu/
│   ├── mcp_server.py        Public repository tool registration and schemas
│   ├── models.py           Shared metadata, snapshots, and errors
│   ├── rest/               DSpace search, files, and Dataverse datasets
│   └── oai/                OAI-PMH client, parser, models, and service
├── library/
│   ├── mcp_server.py        Library tool registration and schemas
│   ├── personal_tools.py    Local authenticated facility tool
│   ├── models.py           Catalogue, access and facility responses
│   ├── client.py           OneSearch requests and pagination
│   ├── facilities.py       Public facility directory and map availability
│   ├── session.py          Optional facility login and daily time grids
│   ├── schedule.py         Time-grid validation and normalization
│   └── parser.py           Primo record normalization
├── faculty/
│   ├── mcp_server.py        Public faculty tools and input schemas
│   ├── models.py           Typed profile and research-interest responses
│   ├── client.py           Directory requests, filters, and pagination
│   └── parser.py           Profile cards and interest form parsing
├── news/
│   ├── mcp_server.py        Public news tools and input schemas
│   ├── models.py           Typed story, category, and article responses
│   ├── client.py           News search and bounded article retrieval
│   └── parser.py           Story cards and article body extraction
├── service/
│   ├── mcp_server.py        Public campus service tools and input schemas
│   ├── models.py           Typed location and filter responses
│   ├── client.py           Complete directory collection and local search
│   └── parser.py           Contact, hours, and map normalization
├── omnibus/                Public shuttle and LTA stops, positions, arrivals and schedules
└── onestop/                Local ServiceNow reads and native workflows
tests/
├── stars/                  STARS tests and fictionalized fixtures
├── ntulearn/               NTULearn tests and synthetic fixtures
├── mazemap/                MazeMap tests and synthetic fixtures
├── repository/             DR-NTU tests and synthetic fixtures
├── library/                OneSearch and LibFacilities tests and fixtures
├── faculty/                Faculty directory tests and synthetic fixtures
├── news/                   News search and article tests with synthetic fixtures
├── service/                Campus directory tests and synthetic fixtures
├── hosted/                 Public HTTP protocol, isolation, and deployment checks
├── test_*.py               Keyring, local CLI, and shared lifecycle tests
└── typescript_smoke.mjs     Shared MCP interoperability check
```

## Tools

### STARS

Public lookups work without credentials. Planner and Degree Audit use the shared NTU credentials.

| Tool | Purpose | Credentials |
| --- | --- | --- |
| `stars_search_courses` | Find undergraduate courses by partial code or title keywords in a published term | No |
| `stars_get_course_metadata` | Course name, AUs, prerequisites, description, and term metadata | No |
| `stars_get_prerequisite_tree` | Explore a course's prerequisites and dependent courses with separate depth limits | No |
| `stars_get_course_indexes` | Paginated indexes with schedules, vacancies, and waitlist lengths | No |
| `stars_get_index` | One index's complete schedule, vacancies, and waitlist length | No |
| `stars_compare_indexes` | Shared sessions, index-specific sessions, and optional clash checks | No |
| `stars_find_matching_indexes` | Filter by days, times, lesson types, teaching weeks, and supplied schedule clashes | No |
| `stars_find_available_rooms` | Teaching-observed rooms with no scheduled classes in a time/week window | No |
| `stars_get_room_schedule` | Courses, indexes and lessons using a room | No |
| `stars_get_graduate_course_schedule` | Graduate course class groups and scheduled sessions | No |
| `stars_get_undergraduate_exam_schedule` | Undergraduate exam date, time, duration, and published-term notice | No |
| `stars_auth_status` | Whether optional WISH credentials are configured and a session has been verified | No |
| `stars_get_stars_planner` | Your registered courses and saved Plans 1–3 with timetables | Yes |
| `stars_save_stars_plan` | Replace a saved plan's course/index list and verify the saved result | Yes |
| `stars_get_degree_audit` | Your AU requirements, results, and registered courses | Yes |

Vacancies are available **09:00–22:00 Singapore time**; unknown counts are `null`. Saving a plan replaces its entire course/index list. See the [STARS guide](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/stars/README.md) for parameters, examples, and sources.

`stars_get_course_indexes` returns 10 indexes by default. Follow `next_offset` to retrieve subsequent pages, or supply `limit` up to 50. Use `stars_get_index` for one index's full schedule.

### NTULearn

| Tool | Purpose | Credentials |
| --- | --- | --- |
| `ntulearn_auth_status` | Credential configuration and last verified session | No |
| `ntulearn_list_courses` | Your enrolled courses and organizations, with availability and IDs | Yes |
| `ntulearn_get_course_contents` | One level of course content, with `parent_id` to open a folder | Yes |
| `ntulearn_get_announcements` | Published announcements for one course | Yes |
| `ntulearn_get_calendar` | Calendar entries and published deadlines | Yes |
| `ntulearn_get_upcoming` | All calendar pages across enrolled or selected courses | Yes |
| `ntulearn_get_gradebook` | Gradebook columns and your own visible scores and status | Yes |
| `ntulearn_get_content_attachments` | Attached files for a leaf content item | Yes |
| `ntulearn_read_file_content` | Read PDF, Office, and text attachments inline | Yes |
| `ntulearn_download_file` | Save an attachment to a new, explicit local file path | Yes |
| `ntulearn_list_messages` | List inbox or sent messages from course conversations | Yes |
| `ntulearn_read_message` | Full message body and published conversation recipients | Yes |
| `ntulearn_list_course_users` | Visible course users and their roles | Yes |
| `ntulearn_list_course_groups` | Course groups and group sets | Yes |
| `ntulearn_get_group_members` | Visible members of a course group | Yes |
| `ntulearn_search_course_content` | Recursive substring search within one course | Yes |
| `ntulearn_search_all_courses` | Search course content with course IDs and breadcrumbs | Yes |
| `ntulearn_get_content_tree` | Nested course content tree bounded by depth and size | Yes |
| `ntulearn_download_course` | Download course attachments into local folders | Yes |
| `ntulearn_whats_new` | Recent announcements, upcoming events, and grade snapshots | Yes |

Start with `ntulearn_list_courses`, then use the returned IDs. See the [NTULearn guide](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/ntulearn/README.md) for parameters, examples, and sources.

### CareerAxis

CareerAxis tools are local and use the shared NTU OS keyring. They are not exposed by the hosted public server.

| Tool | Purpose | Credentials |
| --- | --- | --- |
| `careeraxis_auth_status` | Report keyring availability and whether this process has verified CareerAxis login | No |
| `careeraxis_search_opportunities` | Search NTU jobs and internship postings by keyword; follow `has_next_page` | Yes |
| `careeraxis_get_opportunity` | Read visible posting text and HTTPS application links from a returned CareerAxis URL | Yes |
| `careeraxis_search_internship_jobs` | Search the Internship workgroup job board | Yes |
| `careeraxis_search_events` | Search events by keyword | Yes |
| `careeraxis_search_resources` | Search career guides, training, and downloadable resources | Yes |
| `careeraxis_search_organisations` | Search employer profiles, optionally requiring current opportunities | Yes |
| `careeraxis_search_appointment_topics` | Find career coaching topics, including interview practice and resume critique | Yes |
| `careeraxis_get_record` | Read details for returned events, resources, employers, appointment topics, or Internship postings | Yes |

Search returns visible portal text without guessing fields CareerAxis does not label consistently. External links are returned for review and never followed; tools do not apply, save items, book appointments, or change account data. Results are cached in memory for 60 seconds by default; set `CAREERAXIS_CACHE_TTL_SECONDS=0` to disable caching. If NTU requires interactive MFA, set `CAREERAXIS_HEADLESS=false` and run the MCP in a visible local session. See the [CareerAxis guide](src/careeraxis/README.md).

### MazeMap

| Tool | Purpose | Credentials |
| --- | --- | --- |
| `mazemap_list_campuses` | NTU campuses and their map IDs | No |
| `mazemap_list_buildings` | Buildings and floor IDs, names, and levels | No |
| `mazemap_search_places` | Find rooms, venues, and amenities by code or name | No |
| `mazemap_get_place` | One place's location, aliases, building, and floor | No |
| `mazemap_get_directions` | Walking instructions, distance, time, and accessibility | No |

Search for a place first, then use its POI ID for details or directions. See the [MazeMap guide](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/mazemap/README.md) for parameters, examples, and sources.

### DR-NTU

| Tool | Purpose | Credentials |
| --- | --- | --- |
| `drntu_search` | Find publications by keywords, repository scope, and facet filters | No |
| `drntu_get_item` | Published metadata, abstracts, citations, and rights | No |
| `drntu_browse` | Explore communities, subcommunities, and collections | No |
| `drntu_get_facets` | Available search filters, values, and result counts | No |
| `drntu_list_bundles` | An item's file groups, including original documents | No |
| `drntu_list_files` | File names, sizes, checksums, rights, and content links | No |
| `drntu_get_dataset` | Published dataset metadata, versions, and file inventories | No |
| `drntu_oai_identify` | Repository identity, date precision, and deletion policy | No |
| `drntu_oai_list_metadata_formats` | Available OAI metadata formats and schemas | No |
| `drntu_oai_list_sets` | OAI collection and community sets | No |
| `drntu_oai_list_records` | Metadata or identifiers filtered by modification date and set | No |
| `drntu_oai_get_record` | One record by its OAI identifier | No |

Public metadata can describe restricted files. See the [DR-NTU guide](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/drntu/README.md) for parameters, examples, and sources.

### Library

| Tool | Purpose | Credentials |
| --- | --- | --- |
| `library_search` | Search OneSearch by keywords, title, author, ISBN, or resource type | No |
| `library_get_record` | Bibliographic metadata, identifiers, descriptions, and access links | No |
| `library_get_availability` | Physical holdings and institutional full-text service links | No |
| `library_list_facilities` | Library facilities, floor maps, and closure notices | No |
| `library_get_map_availability` | Seat and room statuses at a Singapore date and time | No |
| `library_get_facility_schedule` | Daily room and seat time grids and facility descriptions | Yes |

Use the returned record ID and context for details. See the [Library guide](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/library/README.md) for parameters and access limitations.

### Faculty

| Tool | Purpose | Credentials |
| --- | --- | --- |
| `faculty_search` | Find faculty by name or research interest, with public profile details | No |
| `faculty_list_interests` | Research-interest labels and IDs for faculty search | No |

See the [Faculty guide](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/faculty/README.md) for parameters, pagination, and sources.

### News

| Tool | Purpose | Credentials |
| --- | --- | --- |
| `news_search` | Search news by keyword, category, and latest or oldest order | No |
| `news_list_categories` | Published news category labels and filter IDs | No |
| `news_get_article` | Read an article's text in bounded chunks | No |

See the [News guide](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/news/README.md) for parameters and sources.

### NTU Omnibus

| Tool | Purpose | Credentials |
| --- | --- | --- |
| `omnibus_get_live_buses` | Current positions for an NTU shuttle route | No |
| `omnibus_list_routes` | Shuttle route names and published colors | No |
| `omnibus_list_stops` | Search NTU shuttle and LTA stop associations | No |
| `omnibus_get_arrivals` | NTU shuttle and LTA arrival estimates, including services 179 and 199 when present in the feed | No |
| `omnibus_get_service_status` | Shuttle schedules, special-day flags, and temporary notices | No |

Route path geometry is not included in these tools. See the [NTU Omnibus guide](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/omnibus/README.md) for parameters, source behavior, and limits.

### Campus services

| Tool | Purpose | Credentials |
| --- | --- | --- |
| `service_search` | Find food outlets, shops, clinics, and services with hours and contacts | No |
| `service_list_filters` | Official directory type and category filter IDs | No |

See the [Campus services guide](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/service/README.md) for parameters and directory coverage.

### One Stop @ SAC

59 One Stop tools provide reads and native write workflows through the local server, a saved NTU student account, and Chromium. They are not available on the public hosted endpoint. Core discovery tools:

| Tool | Purpose | Credentials |
| --- | --- | --- |
| `onestop_auth_status` | Credential availability and last verified session | No |
| `onestop_list_catalog_categories` | Visible service categories and subcategories | Yes |
| `onestop_list_catalog_items` | Catalog search, category browsing, and popular services | Yes |
| `onestop_get_catalog_item` | Form instructions and fields, excluding personal defaults | Yes |
| `onestop_search_knowledge` | Search student knowledge articles | Yes |
| `onestop_get_knowledge_article` | Read article text and links | Yes |
| `onestop_list_my_requests` | Your open/closed cases and requests, with coverage information | Yes |
| `onestop_get_my_request` | Visible fields, answers and stages for verified own requests/items | Yes |

Additional tools cover request drafts/submission, replies and offered state actions, attachments, article discussions/feedback/subscriptions, dashboard data, profile/preferences, shopping/saved carts, favourites and appointment availability/booking. Payment preparation returns a native gateway link. Writes perform real account actions and should follow the user's specific request. Draft and checkout previews expose validation before submission and guard against duplicate attempts.

One Stop uploads use `~/.config/all-abt-ntu/onestop-uploads` by default (under `$XDG_CONFIG_HOME/all-abt-ntu` when set, or `%APPDATA%\all-abt-ntu\onestop-uploads` on Windows). The folder is created when the upload tool is enabled; you can also create it yourself. Set `NTU_ONESTOP_UPLOAD_DIR` to an absolute directory to override it, or set it to an empty string to disable uploads. Only regular files directly in that directory can be uploaded; the directory itself and the file cannot be symbolic links. Place only files you are willing to make available to the MCP client in that directory. On platforms that cannot enforce this boundary, use the portal's own file picker instead.

Native lists expand up to 500 records where supported; some catalog/search results remain partial. Inspect `complete` and `coverage`; `next_offset` pages retrieved records only. See the [One Stop guide](src/onestop/README.md) for all 59 tools, setup and limitations, including browser handoffs and unverified appointment cancellation/rescheduling.

## Tests

Personal-data, map, repository, library, faculty, news, and service fixtures are synthetic. Timetable fixtures use fictional course labels and indexes while retaining the HTML structures needed for parser tests. Opt-in live tests print counts and statuses; they do not save academic records or learning materials in the repository.

The offline tests cover keyring storage and failure handling, local credential prompts, session recovery, parsing, scheduling, lossless compaction, output-schema validation, tool calls/errors, and resource discovery. Protocol tests use Python SDK clients and an independent JSON-RPC client over stdio, including protocol versions `2025-06-18` and `2025-11-25`:

```sh
uv run python -m unittest discover -s tests -t . -v
```

An optional check uses the official TypeScript SDK. Node dependencies stay in a temporary directory:

```sh
NTU_MCP_TEST_SDK="$(mktemp -d)"
npm install --prefix "$NTU_MCP_TEST_SDK" --ignore-scripts --no-audit --no-fund @modelcontextprotocol/sdk@1.32.1
uv run node tests/typescript_smoke.mjs "$NTU_MCP_TEST_SDK"
```

These interoperability checks use offline fixtures and never edit saved plans.

Hosted HTTP checks cover public-only registration, rejected personal calls, output schemas, both modern and legacy Python SDK clients, Host/Origin validation, request-size limits, and independent serverless event loops. See the [HTTP test instructions](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/shared/README.md#http-tests) for the TypeScript client and opt-in live smoke.

Live checks and service-specific testing instructions: [STARS](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/stars/README.md#tests) · [NTULearn](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/ntulearn/README.md#tests) · [CareerAxis](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/careeraxis/README.md#validation) · [MazeMap](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/mazemap/README.md#tests) · [DR-NTU](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/drntu/README.md#tests) · [Library](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/library/README.md#tests) · [Faculty](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/faculty/README.md#tests) · [News](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/news/README.md#tests) · [Campus services](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/service/README.md#tests) · [NTU Omnibus](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/omnibus/README.md#checks) · [One Stop @ SAC](https://github.com/pitchaya-s/all-abt-ntu-mcp/blob/main/src/onestop/README.md#coverage-runtime-and-checks).

## Limitation

- Access depends on service availability and NTU permissions.
- Timetables are published schedules; vacancies are snapshots.
- NTULearn may restrict content, and large collections can return partial results. Inline document reading extracts text without OCR.
- MazeMap directions are estimates. Map data does not establish room availability or current physical access.
- NTU Omnibus positions and arrivals are live snapshots that can be empty or stale; route path geometry is outside the tool outputs.
- DR-NTU file metadata does not establish download permission. The dataset service may interrupt requests with CAPTCHA.
- Room searches cover published undergraduate teaching only, excluding occupancy, graduate classes, exams, other bookings, and access permissions. Unplaced lesson venues remain outside room-specific coverage.
- Library records and access labels do not establish subscription entitlement, anonymous full-text access, or a loanable copy.
- Facility booking statuses do not establish occupancy. MFA stops library login; no borrowing or facility bookings are submitted.

## Disclaimer

This is an independent project and is not affiliated with, sponsored by, or endorsed by Nanyang Technological University (NTU), Singapore.

Your NTU credentials are retrieved locally from your OS keyring and submitted over HTTPS to NTU or its Microsoft sign-in service. They are never returned through MCP. Academic data returned by tools is visible to the AI client. Keyring storage protects credentials at rest; it does not isolate them from other programs or agents allowed to access your unlocked keyring or the server process.
