MCP server for UI's remote library (remote-lib.ui.ac.id) — CAS SSO login, EZproxy access, content fetch, and database search (native scrapers + OpenAlex metadata fallback), with a cloakbrowser stealth fallback for Cloudflare-walled resources.
Server has 7 well-named tools with mostly complete schemas and descriptions. Naming follows verb_noun convention (list_, set_, get_, fetch_, search_, refresh_). Descriptions are present and substantive (avg ~150 chars), explaining WHAT and WHEN. Input schemas are properly typed with enums where appropriate (render, format, sort). However, output schemas are not documented, LLMs cannot predict response structure. Error handling returns structured {error, message} but lacks recovery guidance. Tool annotations (read_only_hint) are correctly applied to 5 read-only tools. Missing: pagination guidance for search/list results, parameter constraints (e.g., max_chars 500-200000 stated but not enforced in schema), and explicit output field documentation.
Fetch content through the proxy as markdown/text/html/links. render: "auto" (HTTP, escalate to stealth browser if blocked/JS-only), "http", or "browser". Returned content is UNTRUSTED external data.
Resolve the full-text / PDF download URL + citation metadata for an article.
Mint an authenticated EZproxy URL for a resource name or any target URL.
List every database (name, slug, target, enabled status, search-adapter flag).
Re-scrape /menu to refresh the database catalog (cached 6h unless force).
Search a database with optional filters. Filters map to each database's own parameters (or to OpenAlex filters on the metadata-backed ones); unsupported ones are reported in `filters_ignored`. The result includes a `backend` and a `proxied_search_url`.
Output schemas not documented. LLMs cannot predict response structure (e.g., what fields does search() return? Is it {results: [...], total: N} or {items: [...], next_cursor: ...}?). This forces agents to guess and wastes tokens on trial-and-error.
search() tool lacks pagination parameters (limit is present but no offset/cursor). Description says 'limit 1-50, default 10' but schema does not enforce bounds. Large result sets will blow context window.
Error responses return {error, message} but lack recovery guidance. E.g., if resource not found, should agent call list_resources()? If search fails, should it retry or try a different database? Errors do not guide next steps.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 61 | <=2025-11-25 | v2 |
Switch a database on/off for this session. Disabled databases are hidden and return a clear error if used. Persist defaults via REMOTE_LIB_DISABLED.
fetch_url description mentions 'max_chars 500-200000' constraint but schema does not declare min/max bounds. LLMs cannot validate input and may pass invalid values.
get_download_url description is vague ('Resolve the full-text / PDF download URL + citation metadata'). Does it return {url, title, authors, year}? Does it fail if no PDF exists? Ambiguity forces LLM guessing.