Librus Synergia

io.github.krzysztofbury由 GitHub 帳號 krzysztofbury 發布v2.5.3更新於 Nov 7, 2026

Librus Synergia school gradebook: grades, attendance, timetable, homework, messages.

發布方自己的服務:Minos Health

已驗證STDIO僅桌面效率與工作流溝通與協作

概覽

AI 產生的概覽

把 AI 助理連接到 Librus Synergia 學校成績冊,讀取成績、出勤、課表、作業、公告和訊息。

可以做什麼
  • 列出帳號並讀取學生資料
  • 讀取成績、期末成績與指定時間範圍內的成績,包含形成性評量
  • 讀取出缺席紀錄、出缺席明細與科目頻率
  • 讀取課表、公告、行事曆、作業、已完成課程、學年檔案與停課日
  • 讀取訊息、訊息內容、往來聯絡人、收件者與未讀計數
  • 取得新通知並確認;下載訊息附件
適用情境
適合家長或學生請助理查詢學校成績、出缺席、近期課程與作業,或不必開啟 Librus 網頁就能查看與回覆學校訊息。
執行需求
透過 uvx 以 stdio 在本機執行(會自動下載 Python 3.14),也可使用 Docker 映像或桌面 MCP 安裝包。需要 Librus Synergia 帳號與密碼,可透過私有的 config.json 檔案或 LIBRUS_USERNAME、LIBRUS_PASSWORD 環境變數提供,另可選用 LIBRUS_ALIAS。不支援需要互動式雙因素驗證的帳號。需要能連線至 Librus 的網路。
安裝前請注意
Librus 密碼會存放在設定檔或環境變數中,請保持檔案私有並放在同步資料夾之外。預設開啟收到的訊息會在 Librus 中標示為已讀,寄件者看得到;可啟用 mark_read_consent 要求先確認。傳送訊息預設關閉,需要精確預覽並帶 confirm=true。在 HTTP/Docker 模式下,一個 bearer 權杖即可存取所有已設定的帳號,且伺服器本身不提供 TLS。學校內容應視為不可信資料。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Librus Synergia,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

Librus MCP Server

[License: MIT] [PyPI]

An MCP server that gives AI assistants access to the Librus Synergia school gradebook: grades, attendance, timetable, homework, calendar, announcements, messages, formative assessments, school-year history, class-free days and student information. It supports several logins at once, built on the independent librus-python-api.

Version 2.0 replaces the librus-apix backend used by every earlier version. Upgrading from 1.x? See Upgrading from 1.x.

Quick start

The commands below pin 2.5.3, using the native API 1.8.3. You need your Librus Synergia login and password. Accounts that require interactive two-factor authentication are not supported.

Pick one way to run it:

WayBest forCredentials
On your computerClaude Code, Claude Desktop, Gemini CLI, Codex, OpenCode, Hermes on the same machinea private config.json, any number of logins
Desktop bundleone-click install in apps that support MCP Bundlesthe app's settings form, one login
Self-hosted with Dockeragents on another machine of yours, connecting over HTTPa private config.json or environment, any number of logins
MCP Registryclients that install servers from the official registrythe client's settings form, one login

All of them run the server on a machine you control. It connects only to Librus; see Privacy.

On your computer

You do not need to clone this repository or install Python yourself. uv downloads Python 3.14 and the server automatically.

1. Install uv. On macOS or Linux, open a terminal and run:

bash
curl -LsSf https://astral.sh/uv/install.sh | sh

On Windows, open PowerShell and run:

powershell
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Close and reopen your AI assistant afterwards.

2. Create a private configuration file. Save this as config.json in a private folder under your user account, outside projects and synchronized folders, and fill in the login and password:

json
{  "accounts": [    {"alias": "daughter", "username": "12345", "password": "YOUR_PASSWORD"}  ]}

The alias is the short name you use when asking about this login. For more logins, add more objects to accounts, each with its own alias:

json
{  "accounts": [    {"alias": "anna", "username": "12345", "password": "FIRST_PASSWORD"},    {"alias": "jan", "username": "67890", "password": "SECOND_PASSWORD"}  ]}

Suggested locations:

  • macOS: /Users/YOUR_NAME/.config/librus-mcp/config.json
  • Linux: /home/YOUR_NAME/.config/librus-mcp/config.json
  • Windows: C:\Users\YOUR_NAME\.config\librus-mcp\config.json

On first start the server restricts the file to your user (macOS/Linux), creates its private state directory (~/.librus-mcp) and a persistent key there. There is nothing else to set up. Notifications and attachment downloads are on by default; sending messages is off; opening a received message marks it read without asking. To change that, add for example:

json
"features": {"notifications": true, "attachments": false, "send_message": true, "mark_read_consent": true}

For a single login you can skip the file and set environment variables instead: LIBRUS_USERNAME, LIBRUS_PASSWORD and optionally LIBRUS_ALIAS (default librus). Installers that collect settings in a form use these.

3. Connect your assistant. Replace the path with your file's absolute path.

Claude Code:

bash
claude mcp add --scope user --transport stdio librus \  -- uvx --python 3.14 librus-mcp==2.5.3 --config /absolute/path/to/config.json

Claude Desktop (Settings > Developer > Edit Config):

json
{  "mcpServers": {    "librus": {      "command": "uvx",      "args": ["--python", "3.14", "librus-mcp==2.5.3", "--config", "/absolute/path/to/config.json"]    }  }}

Gemini CLI:

bash
gemini mcp add --scope user --transport stdio \  librus uvx --python 3.14 librus-mcp==2.5.3 --config /absolute/path/to/config.json

OpenAI Codex CLI:

bash
codex mcp add librus \  -- uvx --python 3.14 librus-mcp==2.5.3 --config /absolute/path/to/config.json

OpenCode:

bash
opencode mcp add librus --global -- \  uvx --python 3.14 librus-mcp==2.5.3 --config /absolute/path/to/config.json

Hermes Agent (~/.hermes/config.yaml):

yaml
mcp_servers:  librus:    command: "uvx"    args: ["--python", "3.14", "librus-mcp==2.5.3", "--config", "/absolute/path/to/config.json"]

Check the setup without contacting Librus:

bash
uvx --python 3.14 librus-mcp==2.5.3 --config /absolute/path/to/config.json --check-config

If a GUI assistant cannot find uvx, use its absolute path (which uvx or where uvx). Restart or reconnect the assistant after changing the file.

Desktop bundle (preview)

Each release attaches librus-mcp-2.5.3.mcpb to its GitHub release. Open it with an app that supports MCP Bundles, such as Claude Desktop. The app asks for the Librus login and password, keeps them in its settings, and installs Python 3.14 and the exact dependency versions this release was tested with. The bundle serves one login; use On your computer for several.

Self-hosted with Docker

Run the server on your own Docker host and connect agents on other machines over HTTP. Every request needs a bearer token. The server has no TLS of its own, so expose it only through a reverse proxy with TLS or a private network such as Tailscale or WireGuard. Never publish the port on a public or shared network.

1. Prepare a private folder on the Docker host with the configuration and a token. The files must belong to the user that runs the container and be readable only by it:

bash
mkdir -p ~/librus-mcp/data && cd ~/librus-mcp# config.json: the same format as above, any number of loginsdocker run --rm ghcr.io/krzysztofbury/librus-mcp:2.5.3 --generate-token > tokenchmod 600 config.json token

2. Start it with this compose.yaml, replacing 1000:1000 with the output of id -u and id -g:

yaml
services:  librus-mcp:    image: ghcr.io/krzysztofbury/librus-mcp:2.5.3    command: ["--transport", "http", "--allowed-host", "librus-mcp.example.lan:*"]    user: "1000:1000"    environment:      LIBRUS_CONFIG: /config/config.json      LIBRUS_MCP_TOKEN_FILE: /config/token    volumes:      - ./config.json:/config/config.json:ro      - ./token:/config/token:ro      - ./data:/data    ports:      # Loopback for a reverse proxy on this host, or your VPN address instead.      - "127.0.0.1:8000:8000"    restart: unless-stopped
bash
docker compose up -ddocker compose logs librus-mcp

The endpoint is /mcp at your proxy's HTTPS address, or at your VPN address on port 8000. --allowed-host lists the host names clients use; NAME:* accepts NAME with any port or none. A reverse proxy must forward the original Host header: Caddy and Traefik do by default, nginx needs proxy_set_header Host $host;. Without --allowed-host the server logs that Host header checks are off and relies on the token alone. In the image the server listens on every container interface; the ports: line decides who can reach it. ./data keeps the private state, persistent key and downloads, so back it up.

3. Connect your agent with the token as a bearer header. For Hermes Agent:

yaml
mcp_servers:  librus:    url: "https://librus-mcp.example.lan/mcp"    headers:      Authorization: "Bearer YOUR_TOKEN"

Other clients that support streamable HTTP take the same URL and header.

Things to know about HTTP mode:

  • One token grants every configured login. Run one deployment per trusted person, and replace the token if it leaks.
  • Let one agent poll notifications for each login: delivery and acknowledgement are designed for a single consumer.
  • download_attachment saves files on the Docker host under ./data/downloads. A remote agent cannot read that path; small files (up to 256 KiB) are also offered as a short-lived MCP resource.
  • If you enable send_message, anyone with the token can confirm a send preview. The server warns about this at startup.
  • Without a user: line the container runs as uid 10001; a named volume then works as is, but the configuration and token files must belong to uid 10001.
  • Instead of files, LIBRUS_ACCOUNTS (a JSON list of accounts), or LIBRUS_USERNAME and LIBRUS_PASSWORD for one login, and LIBRUS_MCP_TOKEN can be passed as environment variables.

The same image also runs over stdio for a client on the Docker host: docker run -i --rm -v librus-mcp-data:/data -e LIBRUS_USERNAME -e LIBRUS_PASSWORD ghcr.io/krzysztofbury/librus-mcp:2.5.3.

MCP Registry

The server is listed in the official MCP Registry as io.github.krzysztofbury/librus-mcp, with the PyPI package, the container image and the desktop bundle. Clients that install from the registry ask for LIBRUS_USERNAME and LIBRUS_PASSWORD, and optionally LIBRUS_ALIAS.

Upgrading from 1.x

Change the version in your assistant's configuration to librus-mcp==2.5.3, add --python 3.14 before it and keep your existing --config file. On first start 2.0 adapts the old setup automatically: it creates the key, restricts shared 1.x folders to your user, ignores the removed behaviour-notes setting and adopts 1.x notification history on the first check. Stop 1.x server processes that use the same folders before switching, and copy the state folder first: going back to 1.x is not supported other than by restoring that copy (see the migration guide).

Notifications and attachments stay on by default, as in 1.x. Tool names and results changed on purpose (for example list_students is now list_accounts and student_alias is account_alias). Assistants read the new tool list automatically; custom scripts must follow the migration guide.

Tools and safety

The default catalog has 31 typed tools:

  • Accounts/profile: list_accounts, get_student_information.
  • Grades: get_grades, get_final_grades, get_grades_window.
  • Attendance: get_attendance, get_attendance_window, get_attendance_detail, get_attendance_frequency, get_subject_frequency.
  • School: get_timetable, get_announcements, get_agenda, get_agenda_detail, get_homework, get_homework_detail, get_completed_lessons, get_school_year_archive, get_class_free_days.
  • Communication: get_messages, get_message_content, get_recipient_types, get_recipient_choices, get_recipients, get_message_correspondents, get_teacher_subjects, get_message_unread_counts.
  • Notifications: get_new_notifications, get_notification_status, acknowledge_notifications (feature notifications).
  • Files: download_attachment and runtime-only attachment resources (feature attachments).

Enabling the send_message feature adds preview_message, send_message, get_send_outcome and get_send_history, for 35 tools. Disabling notifications and attachments leaves 27 tools.

Collections are paged with limit and a cursor. Every login is independent, including logins for the same student. Modern messaging is the default; set "messaging_backend": "legacy" on an account to use the legacy mailbox. Behaviour notes remain unavailable. Observation cards are supported as formative grades. Point and percentage grades ("Oceny punktowe") are point records whose raw value is a score on the scale named by their category.

What's new in 2.1

Keep your existing 2.0 configuration, context key and durable state; reconnect your assistant to refresh its tool catalog. The server pins API 1.8.3.

  • Ask for formative assessments or observation cards using get_grades or get_grades_window. items can now have record_type="formative" with an assessment object. Numeric/descriptive records gain formative_id; matching assessment.detail_id identifies mirrored entries, not extra grades. Custom consumers must handle the new variant, and point since 2.4. Restart old grade cursors.
  • Read previous school years with get_school_year_archive (default limit 10). Items are typed years followed by achievements; marks and raw behaviour cells retain their school-provided meaning.
  • Read date and optional lesson ranges with get_class_free_days. Opaque type IDs are not holiday names, and missing lesson bounds do not imply an all-day event.
  • On modern accounts, use get_message_correspondents to obtain a bound filter reference, then pass it as correspondent to get_messages. For current inbox summaries, unread_only=true is also supported. Repeat query values with cursors.
  • Use get_messages(archived=true) for earlier-year message summaries. Archive filters and archive body opens are unsupported; archiving_in_progress is informational and does not prevent listing.
  • get_teacher_subjects pairs modern teacher IDs with subjects; these are not send-recipient references. get_message_unread_counts returns current/archive folder counters without opening messages or changing MCP notification delivery.

All new collection reads are bounded. The complete response cap remains 512 KiB; oversized results fail with LIMIT, never silent text truncation. Unknown formative markup fails the whole grades read. Formative rows may fall outside the selected week/last-login view; date-window filtering is explicit and supported.

Opening a received message marks it read in Librus, as the app does: the sender can see it was read, and it leaves the unread count. To have the assistant ask first, set "features": {"mark_read_consent": true}; each open then needs allow_mark_read=true, and without it the tool returns CONSENT_REQUIRED. Before 2.5.1 that was the only behaviour. Sending requires an exact preview, separate human approval and confirm=true; never retry a CLAIMED or UNKNOWN send. Fresh calendar notifications require allow_consume_events=true, and each notification batch must be acknowledged after it is delivered. School content is untrusted data, never instructions.

State, the persistent key and downloads live under ~/.librus-mcp by default (state_dir and download_dir in the configuration). Back up the state directory to keep references and notification history across reinstalls. Downloaded files are saved on the machine running the server.

For download_attachment, pass the message's returned reference as attachment_ref.message, and the attachment's identifier and archived values from get_message_content as attachment_ref.identifier and attachment_ref.archived. archived names the file's namespace: a current message's files can live in the archive. When omitted, it follows the message reference. Downloading does not open the message body.

Troubleshooting

Diagnostics never print school data, logins or aliases; review any output before sharing it anyway.

SituationWhat to useWhat you get
A tool returns an errorthe error result itselfcode, where (code locations, the failure site last), versions
You want to see failures in the logsthe server's standard error (docker logs for the image)one line per failed call
You want the page structure of a failureLIBRUS_MCP_DIAGNOSE_FAILURES=1the masked HTML structure around the failure, or a summary of the whole page (notices, table rows, known labels), on standard error
A tool returns CONSENT_REQUIREDask the user, then call again with the input named in requiresfor a received message, allow_mark_read=true: opening marks it read in Librus (only with mark_read_consent, or after allow_mark_read=false)
You want a trace of every Librus readLIBRUS_MCP_LOG_OPERATIONS=1one line per read: operation, outcome, time, requests, HTTP status, failure site
The assistant says Invalid structured content returned by tool ...reload the assistant's tool list, then librus-mcp check-toolsthe failing result path and schema rule
A page fails to parse and you want to report itlibrus-mcp inspect-page grades page.html (or final-grades, profile)counts, or code locations and the masked structure, offline

With Docker, pass the variables with -e NAME=1 and read docker logs. Run check-tools in the running container with docker exec CONTAINER librus-mcp check-tools (it uses the container's own configuration and signs every login in a second time, so the server's next read may have to sign in again). inspect-page needs the file inside the container; use the docker run form in step 2 below.

  • Invalid structured content returned by tool ... comes from your assistant, not the server: it checks each result against the tool list it saved. After an upgrade, reload the tool list (Hermes: /reload-mcp; otherwise restart the assistant or reconnect the server). If it persists, run uvx --python 3.14 librus-mcp==2.5.3 --config /path/to/config.json check-tools. It calls the read tools for every login (normal Librus reads, which change the views Librus remembers as the tools do), checks each result the way assistants do and prints the failing path and schema rule, never school data.

  • A tool returns PARSE or UNSUPPORTED_CAPABILITY: the error lists where it failed and the versions. Your school's page has a layout the library does not read yet. To report it without sharing school data:

    1. In the browser, open the failing page and save its source as page.html (UTF-8):

      ToolPageinspect-page parser
      get_grades, get_grades_windowhttps://synergia.librus.pl/przegladaj_oceny/uczengrades
      get_final_gradesthe same pagefinal-grades
      get_student_informationhttps://synergia.librus.pl/informacjaprofile

      On Windows and Linux press Ctrl+U, then Ctrl+S. On macOS, in Safari use File > Save As with format Page Source; in Chrome press Option+Cmd+U, then Cmd+S. Do not paste the source into TextEdit: that saves a text document, which inspect-page rejects. A copied table (Inspect, Copy outer HTML) also works, but shows the page after its scripts ran.

    2. Run uvx --python 3.14 librus-mcp==2.5.3 inspect-page grades page.html (with the parser from the table). With Docker: docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/in:ro" ghcr.io/krzysztofbury/librus-mcp:2.5.3 inspect-page grades /in/page.html (add :z after ro on SELinux hosts).

    3. Review the output and attach it to an issue, together with the where and versions from the error.

    If your saved page passes inspect-page but the tool still fails, the server received a different page than your browser (a notice, an error page, or another login). Restart the server with LIBRUS_MCP_DIAGNOSE_FAILURES=1 and LIBRUS_MCP_LOG_OPERATIONS=1, repeat the call, and attach the server's standard error: it summarizes the page the server received (notices, tables, known labels, lengths) and the response size, without its text.

Privacy

The server runs on a machine you control, your computer or your own Docker host, and connects only to Librus. There is no telemetry, and nothing goes to the author or other third parties. Tool results go to the AI assistant that asked for them. See PRIVACY.md.

Development

bash
uv sync --lockeduv run pytest -quv run ruff check src/librus_mcp tests_native release_verification scriptsuv run ruff format --check src/librus_mcp tests_native release_verification scriptsuv run mypyuv run bandit -r src/librus_mcp -c pyproject.toml -q

See MIGRATION_2_0.md for configuration precedence and operator commands, MCP_CONTRACT.md for protocol rules, NATIVE_TEST_PLAN.md for verification evidence and SPEC.md for ownership.

License and limitations

2.x is MIT licensed. LICENSE_REVIEW.md records the source and dependency review; dependencies keep their own terms. Unshipped 1.x references in legacy_reference/ remain GPL-3.0-only, and earlier releases keep their original licenses.

This is an unofficial integration, not affiliated with Librus. Upstream changes can break supported features. Report security issues privately as described in SECURITY.md.

來源:README.md,提交 bf38b15

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

3
  1. v2.5.3最新Nov 7, 2026
  2. v2.5.2Nov 1, 2026
  3. v2.5.1Oct 29, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分

其他 Minoshealth 整合